home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 October / Chip Ekim 2003.iso / prog / tamsurum / tocom / Security Updates / SQL-MSDE-CriticalUpdate_ENU.msi / Hotfix3 / Files / replmerg.sql < prev    next >
Encoding:
Text File  |  2001-11-19  |  970.6 KB  |  28,679 lines

  1. /*
  2. ** Copyright Microsoft, Inc. 1998-2000
  3. ** All Rights Reserved.
  4. */
  5.  
  6. set nocount on
  7. go
  8.  
  9. execute dbo.sp_configure 'update',1
  10. go
  11. reconfigure with override
  12. go
  13.  
  14. set ANSI_NULLS off
  15. go
  16.  
  17. use master
  18. go
  19.  
  20. dump tran master with no_log
  21. go
  22.  
  23.  
  24.  
  25. /* 
  26. ** Drop the stored procedures in this script using the old dropping SP 
  27. ** and then drop itself
  28. */
  29. if exists (select * from sysobjects
  30.     where type = 'P '
  31.             and name = 'sp_MSdrop_rlcore')
  32. begin
  33.     drop procedure sp_MSdrop_rlcore
  34. end
  35.  
  36. /*
  37. ** Create stored procedures to drop the stored procedures
  38. ** created by this script
  39. */
  40.  
  41. raiserror('Creating procedure sp_MSdrop_rlcore', 0,1)
  42. GO
  43. create procedure sp_MSdrop_rlcore
  44. as
  45.  
  46.     if exists (select * from sysobjects
  47.             where type = 'P'
  48.                 and name = 'sp_MSguidtostr')
  49.         drop procedure sp_MSguidtostr
  50.  
  51.     if exists (select * from sysobjects
  52.             where type = 'P'
  53.                 and name = 'sp_MShelpdestowner')
  54.         drop procedure sp_MShelpdestowner
  55.  
  56.     if exists (select * from sysobjects
  57.             where type = 'P'
  58.                 and name = 'sp_MSchangeobjectowner')
  59.         drop procedure sp_MSchangeobjectowner
  60.  
  61.     if exists (select * from sysobjects
  62.             where type = 'P'
  63.                 and name = 'sp_MSgetcolumnlist')
  64.         drop procedure sp_MSgetcolumnlist
  65.  
  66.     if exists (select * from sysobjects
  67.             where type = 'P'
  68.                 and name = 'sp_MSgetconflicttablename')
  69.         drop procedure sp_MSgetconflicttablename
  70.  
  71.     if exists (select * from sysobjects
  72.             where type = 'P'
  73.                 and name = 'sp_MSuniquetempname')
  74.         drop procedure sp_MSuniquetempname
  75.  
  76.     if exists (select * from sysobjects
  77.             where type = 'P'
  78.                 and name = 'sp_MSuniqueobjectname')
  79.         drop procedure sp_MSuniqueobjectname
  80.  
  81.     if exists (select * from sysobjects
  82.             where type = 'P'
  83.                 and name = 'sp_MSfillupmissingcols')
  84.         drop procedure sp_MSfillupmissingcols
  85.  
  86.     if exists (select * from sysobjects
  87.             where type = 'P'
  88.                 and name = 'sp_MSaddguidcolumn')
  89.         drop procedure sp_MSaddguidcolumn
  90.  
  91.     if exists (select * from sysobjects
  92.             where type = 'P'
  93.                 and name = 'sp_MSprepare_mergearticle')
  94.         drop procedure sp_MSprepare_mergearticle
  95.  
  96.     if exists (select * from sysobjects
  97.             where type = 'P'
  98.                 and name = 'sp_MSuniquecolname')
  99.         drop procedure sp_MSuniquecolname
  100.  
  101.     if exists (select * from sysobjects
  102.             where type = 'P'
  103.                 and name = 'sp_MSaddguidindex')
  104.         drop procedure sp_MSaddguidindex
  105.  
  106.     if exists (select * from sysobjects
  107.             where type = 'P'
  108.                 and name = 'sp_MSrefcnt')
  109.         drop procedure sp_MSrefcnt
  110.     
  111.     if exists (select * from sysobjects
  112.             where type = 'P'
  113.                 and name = 'sp_MSgentablenickname')
  114.         drop procedure sp_MSgentablenickname
  115.     
  116.     if exists (select * from sysobjects
  117.             where type = 'P'
  118.                 and name = 'sp_MStablenickname')
  119.         drop procedure sp_MStablenickname
  120.     
  121.     if exists (select * from sysobjects
  122.         where type = 'P'
  123.             and name = 'sp_MStablenamefromnick')
  124.         drop procedure sp_MStablenamefromnick
  125.  
  126.     if exists (select * from sysobjects
  127.             where type = 'P'
  128.                 and name = 'sp_MSgetmakegenerationapplock')
  129.         drop procedure sp_MSgetmakegenerationapplock
  130.  
  131.     if exists (select * from sysobjects
  132.         where type = 'P'
  133.             and name = 'sp_MSreleasemakegenerationapplock')
  134.         drop procedure sp_MSreleasemakegenerationapplock
  135.  
  136.     if exists (select * from sysobjects
  137.         where type = 'P'
  138.             and name = 'sp_MSmakegeneration')
  139.         drop procedure sp_MSmakegeneration
  140.  
  141.     if exists (select * from sysobjects
  142.             where type = 'P'
  143.                 and name = 'sp_MSfixlineageversions')
  144.         drop procedure sp_MSfixlineageversions
  145.     
  146.     if exists (select * from sysobjects
  147.             where type = 'P'
  148.                 and name = 'sp_MSaddupdatetrigger')
  149.         drop procedure sp_MSaddupdatetrigger
  150.     
  151.     if exists (select * from sysobjects
  152.             where type = 'P'
  153.                 and name = 'sp_MSaddmergetriggers')
  154.         drop procedure sp_MSaddmergetriggers
  155.     
  156.     if exists (select * from sysobjects
  157.                 where type = 'P' and
  158.                 name = 'sp_MSmaptype')
  159.         drop procedure sp_MSmaptype 
  160.  
  161.     if exists (select * from sysobjects
  162.                 where type = 'P' and
  163.                 name = 'sp_MSquerysubtype')
  164.         drop procedure sp_MSquerysubtype 
  165.  
  166.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_showrowreplicainfo')
  167.     begin
  168.         drop procedure sp_showrowreplicainfo
  169.     end
  170.  
  171.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSsethighestversion')
  172.     begin
  173.         drop procedure sp_MSsethighestversion
  174.     end
  175.  
  176.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_mergemetadataretentioncleanup')
  177.     begin
  178.         drop procedure sp_mergemetadataretentioncleanup
  179.     end
  180.  
  181.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSpurgecontentsorphans')
  182.     begin
  183.         drop procedure sp_MSpurgecontentsorphans
  184.     end
  185.     
  186.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_MScleanup_zeroartnick_genhistory')
  187.     begin
  188.         drop procedure sp_MScleanup_zeroartnick_genhistory
  189.     end
  190.     
  191.     if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSdelete_specifiedcontents')
  192.     begin
  193.         drop procedure sp_MSdelete_specifiedcontents
  194.     end
  195.  
  196. go
  197. exec dbo.sp_MS_marksystemobject sp_MSdrop_rlcore
  198. go
  199. exec dbo.sp_MSdrop_rlcore
  200. go
  201.  
  202. dump tran master with no_log
  203. go
  204.  
  205. raiserror('Creating procedure sp_MSguidtostr', 0, 1)
  206. GO
  207.  
  208.  
  209. create proc sp_MSguidtostr (@guid uniqueidentifier, @mystr nvarchar(32) output)
  210.     as
  211. declare @guidstr nvarchar(36)
  212. set @guidstr = convert(nchar(36), @guid)
  213. set @mystr = substring(@guidstr, 1, 8) + substring(@guidstr, 10, 4) +
  214.     substring(@guidstr, 15, 4)+ substring(@guidstr, 20, 4)+ substring(@guidstr, 25, 12)
  215. go
  216. exec dbo.sp_MS_marksystemobject sp_MSguidtostr
  217. go
  218.  
  219. raiserror('Creating procedure sp_MSgetconflicttablename', 0,1)
  220. GO
  221.  
  222. CREATE PROCEDURE sp_MSgetconflicttablename
  223. @publication sysname,
  224. @source_object nvarchar(520),
  225. @conflict_table sysname = NULL OUTPUT
  226. AS
  227.  
  228. declare @objid                 int
  229. declare @retcode            int
  230. declare @current_conflict    sysname
  231. declare @object_name        sysname
  232. declare @name_out            sysname
  233. declare @pubid                uniqueidentifier
  234. declare @article            sysname
  235. declare @tablename          sysname
  236. declare @ownername          sysname
  237.  
  238. select @tablename = null
  239. select @ownername = null
  240.  
  241. select @pubid=pubid from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name()
  242.  
  243. select @objid = object_id(@source_object)
  244.  
  245. -- Raise error if objid is still null at this point
  246. if @objid is null
  247. begin
  248.     declare @db_name sysname
  249.     select @db_name = db_name()
  250.     raiserror(15009,16, -1,@source_object,@db_name)
  251.     return 1  
  252. end
  253. select @article=name, @current_conflict = conflict_table from sysmergearticles where objid = @objid and pubid=@pubid
  254. if @current_conflict is not NULL
  255.     begin
  256.         if @conflict_table is NULL
  257.             select @current_conflict
  258.         else    
  259.             select @conflict_table = @current_conflict
  260.         return (0)
  261.     end
  262.  
  263. if len(@publication) + len(@article) > 118         -- SYSNAME minus 'conflict_'
  264.     select @object_name = 'conflict_' + convert(nvarchar(59), @publication) + '_' + convert(nvarchar(59), @article)
  265. else
  266.     select @object_name = 'conflict_' + @publication + '_' + @article
  267. exec @retcode = dbo.sp_MSuniqueobjectname @object_name, @conflict_table OUTPUT
  268.  
  269. GO
  270.  
  271. exec dbo.sp_MS_marksystemobject sp_MSgetconflicttablename
  272. go
  273. grant exec on dbo.sp_MSgetconflicttablename to public
  274. go
  275.  
  276. raiserror('Creating procedure sp_MSuniqueobjectname', 0,1)
  277. GO
  278.  
  279. CREATE PROCEDURE sp_MSuniqueobjectname 
  280.     @name_in sysname,
  281.      @name_out sysname = NULL output
  282. AS
  283.  
  284.      declare @name_out_local sysname
  285.     declare @subschars         sysname
  286.     declare @curchar         nchar(1)
  287.     declare @substidx         int
  288.     declare @pos             int
  289.  
  290.     select @subschars = 'abcdefghijklmnopqrstuvwxyz'
  291.     select @name_out_local = @name_in
  292.  
  293.  
  294.     select @substidx = 0
  295.     select @pos = 1
  296.  
  297.     while exists (select * from sysobjects where name = @name_out_local)
  298.         begin
  299.         if @substidx > 25 
  300.             begin
  301.             select @pos = @pos + 1
  302.             select @substidx = 1
  303.             end
  304.         else
  305.             select @substidx = @substidx + 1
  306.         select @curchar = substring(@subschars, @substidx, 1)
  307.         select @name_out_local = stuff(@name_out_local, @pos, 1, @curchar)
  308.         end
  309.  
  310.     if @name_out IS NULL
  311.         select @name_out_local
  312.     else
  313.         select @name_out = @name_out_local
  314.  
  315.     return (0)
  316. GO
  317.  
  318. exec dbo.sp_MS_marksystemobject sp_MSuniqueobjectname 
  319. go
  320.  
  321.  
  322. raiserror('Creating procedure sp_MSuniquetempname', 0,1)
  323. GO
  324.  
  325. CREATE PROCEDURE sp_MSuniquetempname @name_in sysname,
  326.      @name_out sysname output
  327. AS
  328.  
  329.     declare @subschars nvarchar(26)
  330.     declare @curchar nchar(1)
  331.     declare @substidx int
  332.     declare @pos int
  333.     declare @saverr int
  334.  
  335.     select @subschars = 'abcdefghijklmnopqrstuvwxyz'
  336.     select @saverr = @@error
  337.     if (@saverr <> 0)
  338.         goto EXIT_LABEL
  339.     select @name_out = @name_in
  340.     select @saverr = @@error
  341.     if (@saverr <> 0)
  342.         goto EXIT_LABEL
  343.  
  344.     select @saverr = @@error
  345.     if (@saverr <> 0)
  346.         goto EXIT_LABEL
  347.     select @substidx = 0
  348.     select @pos = 3
  349.  
  350.     while exists (select * from tempdb..sysobjects where name = @name_out)
  351.         begin
  352.             if @substidx > 25 
  353.                 begin
  354.                 select @pos = @pos + 1
  355.                 select @substidx = 1
  356.                 end
  357.             else
  358.                 select @substidx = @substidx + 1
  359.             select @curchar = substring(@subschars, @substidx, 1)
  360.             select @saverr = @@error
  361.             if (@saverr <> 0)
  362.                 goto EXIT_LABEL
  363.             select @name_out = stuff(@name_out, @pos, 1, @curchar)
  364.             select @saverr = @@error
  365.             if (@saverr <> 0)
  366.                 goto EXIT_LABEL
  367.         end
  368.         return (0)
  369. EXIT_LABEL:
  370.     if (@saverr <> 0)
  371.         begin
  372.             RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
  373.             return (1)
  374.         end
  375.             
  376. GO
  377. exec dbo.sp_MS_marksystemobject sp_MSuniquetempname 
  378. go
  379.  
  380. raiserror('Creating procedure sp_MSuniquecolname', 0,1)
  381. GO
  382.  
  383. create procedure sp_MSuniquecolname
  384.     @table_name nvarchar(270),  -- this is a qualified_name         
  385.     @base_colname sysname, 
  386.     @unique_colname sysname output
  387. as
  388. begin
  389.     
  390.     set nocount on
  391.     
  392.     declare @icol_suffix int
  393.     
  394.     select @icol_suffix = ( max(colorder) + 1 ) from syscolumns 
  395.         where id = object_id( @table_name )
  396.  
  397.     select @unique_colname = @base_colname 
  398.  
  399.     while exists( 
  400.             select * from syscolumns 
  401.                 where id = object_id( @table_name ) 
  402.                   and name = @unique_colname
  403.     )
  404.     begin
  405.         select @unique_colname = @base_colname + convert( nvarchar(40), @icol_suffix )      
  406.         select @icol_suffix = @icol_suffix * ( @@spid + 1 )
  407.     end
  408.     
  409. end
  410. go
  411.  
  412. exec dbo.sp_MS_marksystemobject sp_MSuniquecolname
  413. go
  414.  
  415. raiserror('Creating procedure sp_MSaddguidcolumn', 0,1)
  416. GO
  417.  
  418. SET ANSI_NULLS ON 
  419. SET QUOTED_IDENTIFIER ON
  420. go
  421. create procedure sp_MSaddguidcolumn
  422.     @source_owner    sysname,
  423.     @source_table     sysname         /* table name */
  424. as
  425.     declare @rowguidcol         sysname
  426.     declare @id                    int
  427.     declare @qualified_name        nvarchar(270)
  428.     declare @columns            varbinary(128)
  429.     declare @retcode            int
  430.     declare @colid                int
  431.     declare @pubid                uniqueidentifier
  432.  
  433.     set nocount on
  434.         
  435.     select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
  436.     select @id = object_id(@qualified_name)
  437.     
  438.     /* Alter the source table to add a rowguid column */
  439.     begin tran
  440.     save tran sp_MSaddguidcolumn
  441.     exec dbo.sp_MSunmarkreplinfo @source_table, @source_owner
  442.     if @@ERROR <>0 goto UNDO
  443.  
  444.     if not exists (select * from syscolumns
  445.         where ObjectProperty(object_id(@qualified_name), 'tablehasrowguidcol')=1)
  446.     begin
  447.         exec dbo.sp_MSuniquecolname @qualified_name, 'rowguid', @rowguidcol output
  448.         exec ('alter table ' + @qualified_name + ' add ' + @rowguidcol + ' uniqueidentifier ROWGUIDCOL default newid() not null')
  449.         if @@ERROR<>0 goto UNDO
  450.     end
  451.     exec dbo.sp_MSunmarkreplinfo @source_table, @source_owner, 1
  452.     if @@ERROR<>0 goto UNDO
  453.     
  454.     commit tran
  455.     return (0)
  456. UNDO:
  457.     rollback tran sp_MSaddguidcolumn
  458.     commit tran
  459.     return (1)    
  460. go
  461.  
  462. exec dbo.sp_MS_marksystemobject sp_MSaddguidcolumn 
  463. go
  464. grant exec on dbo.sp_MSaddguidcolumn to public
  465. go
  466. SET ANSI_NULLS OFF
  467. GO
  468. raiserror('Creating procedure sp_MSprepare_mergearticle', 0,1)
  469. GO
  470.  
  471. SET ANSI_NULLS ON 
  472. SET QUOTED_IDENTIFIER ON
  473. go
  474. create procedure sp_MSprepare_mergearticle
  475.     @source_owner    sysname,
  476.     @source_table     sysname,         /* table name */
  477.     @publication     sysname,
  478.     @qualified_tablename     nvarchar(270)
  479. as
  480.     declare @retcode int
  481.     exec @retcode = sp_MSaddguidcolumn @source_owner, @source_table
  482.  
  483.     if @@error <> 0 or @retcode <> 0
  484.         return (1)
  485.  
  486.     exec @retcode = sp_MSaddguidindex @publication, @source_owner, @source_table
  487.  
  488.     if @@error <> 0 or @retcode <> 0
  489.         return (1)
  490.  
  491.     exec @retcode = sp_MSaddmergetriggers @qualified_tablename
  492.  
  493.     if @@error <> 0 or @retcode <> 0
  494.         return (1)
  495. go
  496.  
  497. exec dbo.sp_MS_marksystemobject sp_MSprepare_mergearticle 
  498. go
  499. grant exec on dbo.sp_MSprepare_mergearticle to public
  500. go
  501. SET ANSI_NULLS OFF
  502. GO
  503. raiserror('Creating procedure sp_MSgetcolumnlist', 0,1)
  504. GO               
  505.  
  506. create procedure sp_MSgetcolumnlist(
  507. @pubid                uniqueidentifier,
  508. @column_list         nvarchar(4000) OUTPUT,
  509. @source_objid        int,
  510. @guid_alias            sysname=NULL
  511. )
  512. AS
  513. /* 
  514. ** if it is not vertically partitioned, then get all columns 
  515. ** else get the column list as given in columns of sysmergearticles
  516. */
  517. declare @bitset        int
  518. declare @columns    varbinary(125)
  519. declare @setcolcnt    int
  520. declare @colcnt        int
  521. declare @colname    nvarchar(140)
  522. declare @colid        int
  523. declare @unqual_sourcename    sysname
  524. declare @qual_sourcename    nvarchar(140)
  525. if @guid_alias is NULL
  526. begin
  527.     select @unqual_sourcename=object_name(@source_objid)
  528.     select @qual_sourcename = QUOTENAME(@unqual_sourcename)
  529. end
  530. else
  531.     select @qual_sourcename=@guid_alias    
  532. select @columns = columns from sysmergearticles where objid = @source_objid and pubid=@pubid
  533. select @column_list = ''
  534. select @setcolcnt    = 0
  535. select @colcnt = count(*) from syscolumns where id = @source_objid
  536. declare collist CURSOR LOCAL FAST_FORWARD FOR 
  537.        select name, colid from syscolumns where id = @source_objid order by colid ASC
  538. FOR READ ONLY
  539. open collist
  540. fetch collist into @colname, @colid
  541. WHILE (@@fetch_status <> -1)
  542. BEGIN
  543.     exec @bitset = sp_MStestbit @columns, @colid
  544. --    if @bitset<>0
  545.     if @bitset<>0 or @columns is null or @columns = ''
  546.     begin
  547.         select @colname = QUOTENAME(@colname) --previously we use rowguidcol to replace 'rowguid'
  548.         if @column_list=''                      --which can cause problems and is not necessary.
  549.             select @column_list = @qual_sourcename + '.' + @colname
  550.         else
  551.             select @column_list = @column_list + ', ' + @qual_sourcename + '.' + @colname    
  552.         select @setcolcnt = @setcolcnt + 1
  553.     end                    
  554. fetch next from collist into @colname, @colid            
  555. END
  556. close collist
  557. deallocate collist
  558. if @setcolcnt = @colcnt
  559.     select @column_list = ' * '
  560. GO
  561. exec dbo.sp_MS_marksystemobject sp_MSgetcolumnlist 
  562. go
  563. grant exec on dbo.sp_MSgetcolumnlist to public
  564. go
  565.  
  566. raiserror('Creating procedure sp_MSaddguidindex', 0,1)
  567. GO
  568.  
  569. SET ANSI_NULLS ON 
  570. SET QUOTED_IDENTIFIER ON
  571. go
  572. create procedure sp_MSaddguidindex
  573.     @publication     sysname,
  574.     @source_owner    sysname,
  575.     @source_table     sysname        
  576. as
  577.     set nocount on
  578.     declare @indexname     nvarchar(270)
  579.     declare @colname    nvarchar(270)
  580.     declare @retcode int
  581.     declare @qualified_name nvarchar(270)
  582.     declare @colid        int
  583.     declare @columns    varbinary(125)
  584.     declare @id            int
  585.     declare @pubid        uniqueidentifier
  586.       declare @mergepublish    int
  587.  
  588.  
  589.       select @mergepublish = 0x4000
  590.       
  591.     select @pubid = pubid from sysmergepublications 
  592.         where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name()
  593.     select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
  594.     select @id = object_id(@qualified_name)
  595.  
  596.     select @colid=colid from syscolumns where id=@id and columnproperty(@id, name, 'isrowguidcol')=1
  597.     update syscolumns set colstat=colstat | @mergepublish where id=@id and colid=@colid
  598.     if @@ERROR<>0
  599.         return (1)
  600.  
  601.     /* Update the columns bitmaps in all articles at the current publisher that share the same table */
  602.     declare artpubs CURSOR LOCAL FAST_FORWARD FOR 
  603.         select DISTINCT pubid from sysmergearticles where objid=@id and pubid
  604.             in ( select pubid from sysmergepublications where UPPER(publisher) = UPPER(@@SERVERNAME) 
  605.                 and publisher_db = db_name())
  606.     FOR READ ONLY
  607.     open artpubs
  608.     fetch next from artpubs into @pubid
  609.      
  610.     while (@@fetch_status <> -1)
  611.         begin
  612.             select @columns=columns from sysmergearticles where objid=@id and pubid=@pubid
  613.             exec @retcode = sp_MSsetbit @columns OUTPUT, @colid
  614.             if @retcode<>0 or @@ERROR<>0
  615.                 return (1)
  616.             update sysmergearticles set columns=@columns where objid=@id and pubid = @pubid
  617.             if @@ERROR<>0
  618.                 return (1)
  619.             fetch next from artpubs into @pubid
  620.         end 
  621.     close artpubs
  622.     deallocate artpubs
  623.  
  624.    
  625.     select @indexname = 'index_' + convert(nvarchar(36), @id)
  626.  
  627.     /* Make sure index name is unique */
  628.     exec @retcode = dbo.sp_MSuniqueobjectname @indexname, @indexname output
  629.     if @retcode <>0 return (1)
  630.  
  631.     select @colname=name from syscolumns where id=@id and columnproperty(@id, name, 'isrowguidcol')=1
  632.     if (@colname is null)
  633.         return (1)
  634.     
  635.     /* Alter the source table to add a rowguid column */
  636.     if (not exists (select * from sysindexes
  637.         where id = object_id(@qualified_name) and
  638.             @colname = index_col(@qualified_name, indid, 1)
  639.             and indexproperty(id, name, 'IsUnique') = 1 and 
  640.             index_col(@qualified_name, indid, 2) is null))
  641.     begin
  642.         select @colname = N'[' + replace(@colname, N']', N']]') + N']'
  643.         exec ('create unique index ' + @indexname  + ' on ' + @qualified_name + N' (' +  @colname + N')')
  644.         if @@ERROR <>0 return (1) 
  645.     end
  646.     return (0)
  647. go
  648.  
  649.  
  650. exec dbo.sp_MS_marksystemobject sp_MSaddguidindex
  651. go
  652. grant exec on dbo.sp_MSaddguidindex to public
  653. go
  654. SET ANSI_NULLS OFF
  655.  
  656. raiserror('Creating procedure sp_MSrefcnt', 0,1)
  657. GO
  658.  
  659. create procedure sp_MSrefcnt
  660.     @objid int, @refcnt int output
  661. as
  662.     set @refcnt = 0
  663.     create table #temprefs (objid int NOT NULL)
  664.     insert into #temprefs select distinct rkeyid from sysreferences where fkeyid = @objid
  665.  
  666.     while (@@rowcount > 0)
  667.         insert into #temprefs select distinct rkeyid from
  668.             sysreferences where fkeyid in (select objid from #temprefs) and
  669.                 rkeyid not in (select objid from #temprefs)
  670.  
  671.     select @refcnt = count(*) from #temprefs
  672.     return (0)
  673. GO
  674.  
  675. exec dbo.sp_MS_marksystemobject sp_MSrefcnt
  676. go
  677.  
  678.  
  679. raiserror('Creating procedure sp_MSgentablenickname', 0,1)
  680. GO
  681.  
  682. create procedure sp_MSgentablenickname
  683.             @tablenick    int    output, @nickname int, @objid int
  684. as
  685.  
  686.     declare @refcnt int
  687.     declare @retval int
  688.     
  689.     /* Create a tablenickname from the following formula
  690.     **        1.  Get the refcnt, use it for the high order digits so
  691.     **            that processing inserts by ascending tablenickname works well
  692.     **             and processing deletes by descending tablenickname works well.
  693.     **        2.  Use a couple of digits from the nickname so that it is less likely
  694.     **            to collide with tablenickname generated at another merge publisher.
  695.     **        3.  Increment as necessary to make it unique within the publication and database.
  696.     */
  697.     exec @retval = dbo.sp_MSrefcnt @objid, @refcnt output
  698.     if @retval <> 0 return (1)
  699.  
  700.     if @nickname < 0
  701.         set @nickname = 0 - @nickname
  702.  
  703.     /* the biggest value for int is 2147483647, we therefore use another algorithm when
  704.     ** @refcnt is bigger than 200
  705.     */
  706.     if @refcnt < 200
  707.     begin
  708.         set @tablenick = 1000 * ((@refcnt * 10000) + (@nickname % 10000))
  709.         while exists (select * from sysmergearticles where nickname = @tablenick)
  710.             set @tablenick = @tablenick + 1
  711.     end
  712.     else
  713.         select @tablenick=max(nickname) + 1 from sysmergearticles
  714.     return (0)
  715. go
  716.  
  717. exec dbo.sp_MS_marksystemobject sp_MSgentablenickname
  718. go
  719.  
  720. raiserror('Creating procedure sp_MStablenickname', 0,1)
  721. GO
  722.  
  723. create procedure sp_MStablenickname 
  724.     @owner        sysname,
  725.     @tablename     sysname,
  726.     @nick int     output
  727. as
  728.     declare @qualified_name nvarchar(270)
  729.     if @owner is not null
  730.         select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@tablename)
  731.     else 
  732.         select @qualified_name = QUOTENAME(@tablename)
  733.         
  734.     select @nick = nickname from sysmergearticles a, sysobjects o
  735.             where a.objid = o.id and o.id = OBJECT_ID(@qualified_name) and
  736.                 (user_name(uid) = @owner or @owner is null)
  737.     if @nick is NULL return (1)             
  738.     return (0)
  739. go
  740.  
  741. exec dbo.sp_MS_marksystemobject sp_MStablenickname 
  742. go
  743.  
  744. raiserror('Creating procedure sp_MStablenamefromnick', 0,1)
  745. GO
  746.  
  747. create procedure sp_MStablenamefromnick
  748.     @nick int,
  749.     @tablename nvarchar(270) output,
  750.     @pubid uniqueidentifier = NULL
  751. as
  752.     declare @owner sysname
  753.     declare @table sysname
  754.     if (@pubid is null)
  755.         select @table = name, @owner = user_name(uid) from sysobjects where id in (select 
  756.             objid from sysmergearticles where nickname = @nick)
  757.     else
  758.         select @table = name, @owner = user_name(uid) from sysobjects where id in (select 
  759.             objid from sysmergearticles where nickname = @nick and pubid = @pubid)
  760.             
  761.     select @tablename = QUOTENAME(@owner) + '.' + QUOTENAME(@table)
  762.     if (@table is NULL) or (@owner is NULL) 
  763.     begin
  764.         raiserror(21124, 16, -1, @nick)
  765.         return (1) 
  766.     end
  767.     return (0)
  768. go
  769.  
  770. exec dbo.sp_MS_marksystemobject sp_MStablenamefromnick
  771. go
  772.  
  773.  
  774. raiserror('Creating procedure sp_MSgetmakegenerationapplock', 0,1)
  775. GO
  776.  
  777. create procedure sp_MSgetmakegenerationapplock
  778.     @head_of_queue int OUTPUT
  779.     as
  780.     set nocount on
  781.  
  782.     declare @retcode smallint
  783.        declare @lock_resource nvarchar(255)
  784.  
  785.        select @retcode = 0
  786.     select @head_of_queue = 0
  787.     
  788.     select @lock_resource = N'MSinternal_makegeneration_inprogress' + 
  789.                 convert(nvarchar(11), db_id())
  790.  
  791.     
  792.     -- If someone else is making generations / has just made one, exit so
  793.     -- that we won't deadlock
  794.     exec @retcode = sp_getapplock @Resource = @lock_resource,
  795.                                   @LockMode = N'Exclusive',
  796.                                   @LockOwner = N'Session',
  797.                                   @LockTimeout = 0 -- do not wait at all. 
  798.  
  799.     if @@error <> 0 or @retcode < 0
  800.     begin
  801.         -- If the previous applock request timed out, then try again, this time using the default timeout.
  802.         -- Note that even though the -1 lock timeout means indefinite timeout, the query timeout set on the 
  803.         -- session overrides the lock timeout. So it's okay even if the default @@lock_timeout is -1.
  804.         if (@retcode = -1)
  805.         begin
  806.             exec @retcode = sp_getapplock @Resource = @lock_resource,
  807.                         @LockMode = N'Exclusive',
  808.                         @LockOwner = N'Session'
  809.             -- If we succeeded to get the lock, set @lock_acquired to 1 so that the exit code releases the lock.
  810.             if (@retcode >= 0)
  811.             begin
  812.                 goto EXIT_PROC
  813.             end
  814.         end
  815.     end
  816.     else
  817.     begin
  818.         select @head_of_queue = 1
  819.     end
  820.  
  821. EXIT_PROC:
  822.     return @retcode
  823.  
  824. go
  825.  
  826. exec dbo.sp_MS_marksystemobject sp_MSgetmakegenerationapplock 
  827. go
  828. grant exec on dbo.sp_MSgetmakegenerationapplock to public
  829. go
  830.  
  831.  
  832. raiserror('Creating procedure sp_MSreleasemakegenerationapplock', 0,1)
  833. GO
  834.  
  835. create procedure sp_MSreleasemakegenerationapplock
  836.     as
  837.     set nocount on
  838.  
  839.     declare @retcode smallint
  840.        declare @lock_resource nvarchar(255)
  841.  
  842.        select @retcode = 0
  843.     select @lock_resource = N'MSinternal_makegeneration_inprogress' + 
  844.                 convert(nvarchar(11), db_id())
  845.  
  846.        exec @retcode = sp_releaseapplock @Resource = @lock_resource, @LockOwner = N'Session'
  847.        if @@error <> 0 or @retcode < 0
  848.         return (1)    
  849.     else
  850.         return (0)
  851.                 
  852. go
  853. exec dbo.sp_MS_marksystemobject sp_MSreleasemakegenerationapplock 
  854. go
  855. grant exec on dbo.sp_MSreleasemakegenerationapplock to public
  856. go
  857.  
  858.  
  859. raiserror('Creating procedure sp_MSmakegeneration', 0,1)
  860. GO
  861. create procedure sp_MSmakegeneration
  862.     @gencheck int = 0
  863.     as
  864.     set nocount on
  865.  
  866.     declare @gen int
  867.     declare @nick int
  868.     declare @genguid uniqueidentifier
  869.     declare @dt datetime
  870.     declare @dt2 datetime
  871.     declare @art_nick int
  872.     declare @first_ts int
  873.     declare @makenewrow bit
  874.     declare @retcode smallint
  875.     declare @guidnull uniqueidentifier
  876.     declare @nickbin varbinary(255)
  877.     declare @maxgendiff_fornewrow int
  878.     declare @count_of_articles int
  879.     declare @lock_acquired bit
  880.        declare @lock_resource nvarchar(255)
  881.     declare @procfailed bit
  882.     declare @delete_old_genhistory bit
  883.     declare @close_old_genhistory bit
  884.     declare @localize_zeroartnick_generations bit
  885.         
  886.     select @procfailed = 1
  887.        select @retcode = 0
  888.  
  889.     set @guidnull = '00000000-0000-0000-0000-000000000000'
  890.         
  891.     /*
  892.     ** Check to see if current publication has permission
  893.     */
  894.     exec @retcode=sp_MSreplcheck_connection
  895.     if @retcode<>0 or @@ERROR<>0 goto EXIT_PROC
  896.     
  897.     set @genguid = newid()
  898.     exec @retcode=sp_MSgetreplnick @nickname = @nick out
  899.     if @retcode<>0 or @@error<>0 goto EXIT_PROC
  900.  
  901.     -- convert @nick into binary and add a guard byte if needed
  902.     if @nick % 256 = 0
  903.         set @nickbin = convert(binary(4), @nick) + 0x01
  904.     else
  905.         set @nickbin = convert(binary(4), @nick)
  906.  
  907.     select @dt2 = max(coldate) from dbo.MSmerge_genhistory where guidsrc = guidlocal
  908.     set @dt = getdate()
  909.  
  910.     if datediff(dd, @dt2, @dt) = 0
  911.     begin
  912.         if 500 > datediff(ms, @dt2, @dt) and 0 < datediff(ms, @dt2, @dt)
  913.         begin
  914.             select @procfailed = 0
  915.             goto EXIT_PROC
  916.         end
  917.     end
  918.  
  919.     if @gencheck = 3
  920.         set @localize_zeroartnick_generations = 1
  921.     else
  922.         set @localize_zeroartnick_generations = 0
  923.  
  924.     -- localize interrupted generations
  925.     exec @retcode= sp_MSlocalizeinterruptedgenerations @localize_zeroartnick_generations = @localize_zeroartnick_generations
  926.     if @retcode<>0 or @@error<>0 goto EXIT_PROC
  927.  
  928.     -- If @gencheck param is set to 1 ( = ForceConvergence), look for rows with missing generation numbers and set their
  929.     -- gen to 0
  930.     if @gencheck = 1 or @gencheck = 2
  931.     begin
  932.         update dbo.MSmerge_contents set generation = 0 where generation not in
  933.             (select generation from dbo.MSmerge_genhistory)
  934.         update dbo.MSmerge_tombstone set generation = 0 where generation not in
  935.             (select generation from dbo.MSmerge_genhistory)
  936.     end
  937.     /*
  938.     ** If there are no zero generation tombstones or rows, add a dummy row in there. 
  939.     */
  940.        if not exists (select * from dbo.MSmerge_genhistory)
  941.     begin
  942.            insert into dbo.MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) values
  943.             (@genguid, @genguid, 1, 0, @nickbin, @dt)
  944.         if (@@error <> 0) goto EXIT_PROC
  945.     end
  946.  
  947.     select @art_nick = min(nickname), @count_of_articles = count(*) from sysmergearticles
  948.  
  949.     -- Calculate how much less than the max generation in MSmerge_genhistory are we willing to have the minimum open generation in MSmerge_genhistory.
  950.     -- Having a number smaller than or roughly equal to the number of articles will cause more aggressive closing of existing open gens (and making new rows) with 0 changes
  951.     -- and hence more generations for merge agents to deal with. Having a very high number will cause less aggressive closing of open gens but will cause the
  952.     -- common gens of replicas to be stuck at lower numbers because of the existence of "holes" at much lower gen values. An optimization that works well
  953.     -- and is a compromise between the two extremes is to have the max of 100 or (2 * @count_of_articles) + 1 as the max diff we allow before deciding to make a new row.
  954.     if ((2 * @count_of_articles) + 1) > 100
  955.         select @maxgendiff_fornewrow = (2 * @count_of_articles) + 1
  956.     else
  957.         select @maxgendiff_fornewrow = 100
  958.  
  959.     while @art_nick is not null
  960.     begin
  961.         declare @cmd nvarchar(200)
  962.         declare @old_bi_gen int
  963.         declare @bi_objid int
  964.  
  965.         set @old_bi_gen= NULL -- if @old_bi_gen stays NULL: no need to move bi-rows
  966.         set @bi_objid= NULL
  967.         set @delete_old_genhistory = 0
  968.         set @close_old_genhistory = 0
  969.         set @makenewrow = 0
  970.         
  971.         set @bi_objid= (select top 1 before_image_objid from sysmergearticles where nickname = @art_nick)
  972.         if @bi_objid is not null
  973.         begin
  974.             set @cmd= 'update dbo.' + object_name(@bi_objid) + ' set generation= @gen where generation = @oldgen'
  975.         end
  976.         
  977.         begin tran
  978.         save tran sp_MSmakegeneration
  979.         select @gen = max(gen_cur) from sysmergearticles (updlock holdlock) where nickname = @art_nick and gen_cur is not null
  980.  
  981.         -- if either we have no gen_cur set yet, or if we have one but no corresponding genhistory row or we have a closed one which
  982.         -- was bcp-ed in after a reinit, we need to create a new one.
  983.         if @gen is null or 
  984.             (    @gen is not null 
  985.                 and not exists (select generation from dbo.MSmerge_genhistory where generation = @gen and guidlocal = @guidnull)
  986.             )
  987.         begin
  988.             declare @oldgen int
  989.             declare @maxgencur int
  990.  
  991.             set @genguid = newid()
  992.             set @oldgen = @gen
  993.  
  994.             select @gen = COALESCE(1 + max(generation), 1) from dbo.MSmerge_genhistory (updlock)
  995.             
  996.             -- Make sure that the new generation value is not smaller than any existing sysmergearticles.gen_cur.
  997.             select @maxgencur = isnull(max(gen_cur),0) from sysmergearticles where gen_cur is not null
  998.  
  999.             if (@gen <= @maxgencur)
  1000.             begin
  1001.                 set @gen = @maxgencur + 1
  1002.                 -- Now we are guaranteed to not collide with an existing gen_cur
  1003.             end
  1004.             
  1005.             insert into dbo.MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) 
  1006.                 values(@genguid, @guidnull, @gen, @art_nick, @nickbin, @dt)
  1007.             if (@@error <> 0)
  1008.             begin
  1009.                 goto EXIT_RELEASE_TRAN
  1010.             end    
  1011.             
  1012.             update sysmergearticles set gen_cur = @gen where nickname = @art_nick
  1013.             if (@@error <> 0)
  1014.             begin
  1015.                 goto EXIT_RELEASE_TRAN
  1016.             end    
  1017.  
  1018.             -- if this was the case of a gen_cur with no matching genhistory rows, then update the contents and tombstones rows with the new generation value.
  1019.             if @oldgen is not null
  1020.             begin
  1021.                 update dbo.MSmerge_contents set generation = @gen, partchangegen = @gen, joinchangegen = @gen
  1022.                      where generation = @oldgen and partchangegen = @oldgen and tablenick = @art_nick
  1023.                 if (@@error <> 0)
  1024.                 begin
  1025.                     goto EXIT_RELEASE_TRAN
  1026.                 end    
  1027.                 update dbo.MSmerge_contents set generation = @gen, joinchangegen = @gen
  1028.                      where generation = @oldgen and joinchangegen = @oldgen and tablenick = @art_nick
  1029.                 if (@@error <> 0)
  1030.                 begin
  1031.                     goto EXIT_RELEASE_TRAN
  1032.                 end    
  1033.                 update dbo.MSmerge_contents set generation = @gen where generation = @oldgen and tablenick = @art_nick
  1034.                 if (@@error <> 0)
  1035.                 begin
  1036.                     goto EXIT_RELEASE_TRAN
  1037.                 end
  1038.                 update dbo.MSmerge_tombstone set generation = @gen where generation = @oldgen and tablenick = @art_nick
  1039.                 if (@@error <> 0)
  1040.                 begin
  1041.                     goto EXIT_RELEASE_TRAN
  1042.                 end
  1043.  
  1044.                 if @bi_objid is not null
  1045.                 begin
  1046.                     exec dbo.sp_executesql @cmd, N'@gen int, @oldgen int', @gen= @gen, @oldgen= @oldgen
  1047.                     if @@ERROR <> 0 goto EXIT_RELEASE_TRAN
  1048.                 end
  1049.             end
  1050.         end
  1051.             
  1052.         -- these updates should be hitting zero rows...
  1053.         if exists (select * from dbo.MSmerge_contents (readpast readcommitted) where generation = 0 and tablenick = @art_nick)
  1054.         begin
  1055.             update dbo.MSmerge_contents set generation = @gen, partchangegen = @gen, joinchangegen = @gen
  1056.                  where generation = 0 and partchangegen = 0 and tablenick = @art_nick
  1057.             if (@@error <> 0)
  1058.             begin
  1059.                 goto EXIT_RELEASE_TRAN
  1060.             end    
  1061.             update dbo.MSmerge_contents set generation = @gen, joinchangegen = @gen
  1062.                  where generation = 0 and joinchangegen = 0 and tablenick = @art_nick
  1063.             if (@@error <> 0)
  1064.             begin
  1065.                 goto EXIT_RELEASE_TRAN
  1066.             end    
  1067.             update dbo.MSmerge_contents set generation = @gen where generation = 0 and tablenick = @art_nick
  1068.             if (@@error <> 0)
  1069.             begin
  1070.                 goto EXIT_RELEASE_TRAN
  1071.             end
  1072.         end
  1073.             
  1074.         if exists (select * from dbo.MSmerge_tombstone (readpast readcommitted) where generation = 0 and tablenick = @art_nick)
  1075.         begin
  1076.             update dbo.MSmerge_tombstone set generation = @gen where generation = 0 and tablenick = @art_nick
  1077.             if (@@error <> 0)
  1078.             begin
  1079.                 goto EXIT_RELEASE_TRAN
  1080.             end
  1081.         end
  1082.         if not exists (select * from dbo.MSmerge_contents where tablenick = @art_nick and
  1083.                         generation = @gen) and
  1084.            not exists (select * from dbo.MSmerge_tombstone where tablenick = @art_nick and
  1085.                         generation = @gen)
  1086.         begin
  1087.  
  1088.             select @dt2 = coldate from dbo.MSmerge_genhistory where generation = @gen
  1089.             if datediff(dd, @dt2, @dt) = 0 and not exists (select * from dbo.MSmerge_genhistory
  1090.                     where generation > @maxgendiff_fornewrow + @gen)
  1091.             begin
  1092.                 set @makenewrow = 0
  1093.                 set @delete_old_genhistory = 0
  1094.                 
  1095.                 -- If @gencheck param is set to 3 (= OverrideMakeNewGenerations), set the @makenewrow flag
  1096.                 -- This is done for message based merges to ensure that the incomplete gens always get closed
  1097.                 -- during every merge if there are completed generations > than this one.
  1098.                 -- Besides closed generations > this one, we also need to watch out for open generations > this one
  1099.                 -- that have pending changes, and hence sp_MSmakegeneration will eventually close them out. This is
  1100.                 -- required when the @gen just happens to be processed before other open generations with changes.
  1101.                 if @gencheck = 3 
  1102.                 begin
  1103.                     if exists (select * from dbo.MSmerge_genhistory gh 
  1104.                                 where gh.generation > @gen 
  1105.                                 and gh.guidlocal <> @guidnull)
  1106.                         or exists (select * from dbo.MSmerge_contents mc where mc.generation > @gen)
  1107.                         or exists (select * from dbo.MSmerge_tombstone mt where mt.generation > @gen)
  1108.                     begin
  1109.                         set @makenewrow = 1
  1110.                         set @old_bi_gen= @gen -- we will move bi-rows
  1111.                         set @delete_old_genhistory = 1
  1112.                     end
  1113.                 end                
  1114.             end
  1115.             else
  1116.             begin
  1117.                 set @makenewrow = 1
  1118.                 set @old_bi_gen= @gen -- we will move bi-rows
  1119.                 set @delete_old_genhistory = 1
  1120.             end
  1121.         end
  1122.         else
  1123.         begin
  1124.             set @makenewrow = 1
  1125.             set @delete_old_genhistory = 0    -- don't delete existing genhistory row. just mark it as closed.
  1126.             set @close_old_genhistory = 1
  1127.         end
  1128.  
  1129.         if (@makenewrow = 1)
  1130.         begin
  1131.             declare @newgen int
  1132.  
  1133.             /* reset next generation for this article */
  1134.             set @genguid = newid()
  1135.             insert into dbo.MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) 
  1136.                 select @genguid, @guidnull, COALESCE(1 + max(generation), 1), @art_nick, @nickbin, @dt from dbo.MSmerge_genhistory (updlock)
  1137.             if (@@error <> 0)
  1138.             begin
  1139.                 goto EXIT_RELEASE_TRAN
  1140.             end    
  1141.             select @newgen  =  generation  from dbo.MSmerge_genhistory where guidsrc = @genguid
  1142.             update sysmergearticles set gen_cur = @newgen where nickname = @art_nick
  1143.             if (@@error <> 0)
  1144.             begin
  1145.                 goto EXIT_RELEASE_TRAN
  1146.             end    
  1147.  
  1148.             if @bi_objid is not null and @old_bi_gen is not NULL
  1149.             begin
  1150.                 exec dbo.sp_executesql @cmd, N'@gen int, @oldgen int', @gen = @newgen, @oldgen = @old_bi_gen
  1151.                 if @@ERROR <> 0 goto EXIT_RELEASE_TRAN
  1152.             end
  1153.         end
  1154.  
  1155.         if (@delete_old_genhistory = 1)
  1156.         begin
  1157.             declare @error int
  1158.             declare @genhistory_rowsdeleted int
  1159.  
  1160.             -- delete the old genhistory row only if there still aren't any rows in contents or 
  1161.             -- tombstone with this generation value. Note that after the previous update statement on sysmergearticles
  1162.             -- no new spids can take locks on sysmergearticles and hence cannot 
  1163.             -- insert any new rows with the old gen_cur.
  1164.             delete from dbo.MSmerge_genhistory 
  1165.             where generation = @gen
  1166.             and not exists (select * from dbo.MSmerge_contents where tablenick = @art_nick and generation = @gen) 
  1167.             and not exists (select * from dbo.MSmerge_tombstone where tablenick = @art_nick and generation = @gen)
  1168.  
  1169.             select @genhistory_rowsdeleted = @@rowcount, @error = @@error
  1170.  
  1171.             -- If the genhistory row which we previously thought could be deleted, now has changes in contents or 
  1172.             -- tombstone, it's okay to not delete it and still leave it as open. In future this open generation
  1173.             -- will be treated as an interrupted generation and the changes in it will be moved to a new local 
  1174.             -- generation. So there will be convergence. Deleting the genhistory row based on incorrect past determination
  1175.             -- of 0 changes is dangerous and can easily cause non-convergence.
  1176.             -- The best solution is to close this generation if we finally didn't delete it. The reason is that it
  1177.             -- allows subscribers to move their last received watermark higher than this open generation.
  1178.             if @genhistory_rowsdeleted = 0
  1179.             begin
  1180.                 set @close_old_genhistory = 1
  1181.             end
  1182.  
  1183.             if (@error <> 0)
  1184.             begin
  1185.                 goto EXIT_RELEASE_TRAN
  1186.             end    
  1187.         end
  1188.  
  1189.         if (@close_old_genhistory = 1)
  1190.         begin
  1191.             set @genguid = newid()
  1192.             update dbo.MSmerge_genhistory set guidsrc = @genguid, guidlocal = @genguid, coldate = @dt
  1193.                 where generation = @gen
  1194.             if (@@error <> 0)
  1195.             begin
  1196.                 goto EXIT_RELEASE_TRAN
  1197.             end    
  1198.             update MSmerge_replinfo set recgen = @gen, recguid = @genguid, 
  1199.                 sentgen = @gen, sentguid = @genguid where replnickname = @nick
  1200.             if (@@error <> 0)
  1201.             begin
  1202.                 goto EXIT_RELEASE_TRAN
  1203.             end    
  1204.         end
  1205.  
  1206.         commit transaction        
  1207.  
  1208.         -- set up for next time through the loop
  1209.         select @art_nick = min(nickname) from sysmergearticles where nickname > @art_nick
  1210.         
  1211.         set @dt = getdate()
  1212.     end
  1213.  
  1214.     select @procfailed = 0
  1215.         
  1216. EXIT_RELEASE_TRAN:
  1217.  
  1218.     if (@procfailed = 1)
  1219.     begin
  1220.         rollback tran sp_MSmakegeneration
  1221.         commit transaction
  1222.     end
  1223.  
  1224. EXIT_PROC:
  1225.  
  1226.     if (@procfailed = 1)
  1227.         return (1)    
  1228.     else
  1229.         return (0)
  1230. go
  1231.  
  1232. exec dbo.sp_MS_marksystemobject sp_MSmakegeneration 
  1233. go
  1234. grant exec on dbo.sp_MSmakegeneration to public
  1235. go
  1236.  
  1237. raiserror('Creating procedure sp_MSfixlineageversions', 0,1)
  1238. GO
  1239.  
  1240. create procedure sp_MSfixlineageversions
  1241. as
  1242.     declare @lNick int -- length of nickname in bytes
  1243.     declare @lVer int -- length of version in bytes
  1244.     declare @lEntry int -- length of entry in bytes
  1245.     declare @cEntries int
  1246.     declare @idx int -- @idx is the index of the entry that potentially needs to be bumped up
  1247.     set @lNick= 4
  1248.     set @lVer= 4
  1249.     set @lEntry= @lNick + @lVer
  1250.     set @cEntries= 31 -- max number of entries        
  1251.  
  1252.     if exists (select * from sysobjects where type = 'U' and name = 'MSmerge_contents')
  1253.     begin
  1254.         -- starting at the end of the lineage, replace every lower version by the following higher version
  1255.         set @idx= @cEntries - 2    -- lineage entries range from 0..30; compare 30 with 29, then 29 with 28, ..., 1 with 0
  1256.         while @idx >= 0
  1257.         begin
  1258.             update dbo.MSmerge_contents set lineage= 
  1259.                 -- leave everything before "entry[@idx].version" unmodified
  1260.                 substring(lineage, 1, @idx * @lEntry + @lNick) + 
  1261.                 -- replace "entry[@idx].version" by "entry[@idx+1].version"
  1262.                 substring(lineage, (@idx + 1) * @lEntry + @lNick + 1, @lVer) +    
  1263.                 -- leave everything starting at "entry[@idx+1].nickname" unmodified
  1264.                 substring(lineage, (@idx + 1) * @lEntry + 1, (@cEntries * @lEntry) - ((@idx + 1) * @lEntry) + 1) -- '+1' is for trailing byte
  1265.                 where
  1266.                     -- skip this step right away for shorter lineages
  1267.                     datalength(lineage) >= @lEntry * (@idx + 2)
  1268.                     and
  1269.                     (
  1270.                         -- either least significant version byte at second entry is higher, the other three are equal
  1271.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 1, 1) > substring(lineage, @idx * @lEntry + @lNick + 1, 1) and
  1272.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 2, 3) = substring(lineage, @idx * @lEntry + @lNick + 2, 3))
  1273.                         or
  1274.                         -- 2nd least significant version byte at second entry is higher, the most and 2nd most significant bytes are equal
  1275.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 2, 1) > substring(lineage, @idx * @lEntry + @lNick + 2, 1) and
  1276.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 3, 2) = substring(lineage, @idx * @lEntry + @lNick + 3, 2))
  1277.                         or
  1278.                         -- 3rd least significant version byte at second entry is higher, the most significant byte is equal
  1279.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 3, 1) > substring(lineage, @idx * @lEntry + @lNick + 3, 1) and
  1280.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 4, 1) = substring(lineage, @idx * @lEntry + @lNick + 4, 1))
  1281.                         or
  1282.                         -- most significant byte at second entry is higher
  1283.                         substring(lineage, (@idx + 1) * @lEntry + @lNick + 4, 1) > substring(lineage, @idx * @lEntry + @lNick + 4, 1)
  1284.                     )
  1285.  
  1286.             if @@error<>0
  1287.             begin
  1288.                 return (1)
  1289.             end
  1290.  
  1291.             set @idx= @idx - 1
  1292.         end
  1293.     end
  1294.     if exists (select * from sysobjects where type = 'U' and name = 'MSmerge_tombstone')
  1295.     begin
  1296.         -- starting at the end of the lineage, replace every lower version by the following higher version
  1297.         set @idx= @cEntries - 2    -- lineage entries range from 0..30; compare 30 with 29, then 29 with 28, ..., 1 with 0
  1298.         while @idx >= 0
  1299.         begin
  1300.             update dbo.MSmerge_tombstone set lineage= 
  1301.                 -- leave everything before "entry[@idx].version" unmodified
  1302.                 substring(lineage, 1, @idx * @lEntry + @lNick) + 
  1303.                 -- replace "entry[@idx].version" by "entry[@idx+1].version"
  1304.                 substring(lineage, (@idx + 1) * @lEntry + @lNick + 1, @lVer) +    
  1305.                 -- leave everything starting at "entry[@idx+1].nickname" unmodified
  1306.                 substring(lineage, (@idx + 1) * @lEntry + 1, (@cEntries * @lEntry) - ((@idx + 1) * @lEntry) + 1) -- '+1' is for trailing byte
  1307.                 where
  1308.                     -- skip this step right away for shorter lineages
  1309.                     datalength(lineage) >= @lEntry * (@idx + 2)
  1310.                     and
  1311.                     (
  1312.                         -- either least significant version byte at second entry is higher, the other three are equal
  1313.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 1, 1) > substring(lineage, @idx * @lEntry + @lNick + 1, 1) and
  1314.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 2, 3) = substring(lineage, @idx * @lEntry + @lNick + 2, 3))
  1315.                         or
  1316.                         -- 2nd least significant version byte at second entry is higher, the most and 2nd most significant bytes are equal
  1317.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 2, 1) > substring(lineage, @idx * @lEntry + @lNick + 2, 1) and
  1318.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 3, 2) = substring(lineage, @idx * @lEntry + @lNick + 3, 2))
  1319.                         or
  1320.                         -- 3rd least significant version byte at second entry is higher, the most significant byte is equal
  1321.                         (substring(lineage, (@idx + 1) * @lEntry + @lNick + 3, 1) > substring(lineage, @idx * @lEntry + @lNick + 3, 1) and
  1322.                             substring(lineage, (@idx + 1) * @lEntry + @lNick + 4, 1) = substring(lineage, @idx * @lEntry + @lNick + 4, 1))
  1323.                         or
  1324.                         -- most significant byte at second entry is higher
  1325.                         substring(lineage, (@idx + 1) * @lEntry + @lNick + 4, 1) > substring(lineage, @idx * @lEntry + @lNick + 4, 1)
  1326.                     )
  1327.  
  1328.             if @@error<>0
  1329.             begin
  1330.                 return (1)
  1331.             end
  1332.  
  1333.             set @idx= @idx - 1
  1334.         end
  1335.     end
  1336.     return (0)
  1337. go
  1338.  
  1339. exec dbo.sp_MS_marksystemobject sp_MSfixlineageversions 
  1340. go
  1341. grant exec on dbo.sp_MSfixlineageversions to public
  1342. go
  1343.  
  1344. dump tran master with no_log
  1345. go
  1346.  
  1347. raiserror('Creating procedure sp_MSaddupdatetrigger', 0,1)
  1348. GO
  1349.  
  1350. CREATE PROCEDURE sp_MSaddupdatetrigger 
  1351.     @source_table        nvarchar(270),        /* source table name */
  1352.     @owner                sysname,            /* Owner name of source table */
  1353.     @object             sysname,            /* Object name */
  1354.     @artid                uniqueidentifier,    /* Article id */
  1355.     @column_tracking        int,
  1356.     @viewname            sysname             /* name of view on syscontents */
  1357.     
  1358. AS
  1359.     declare @command1 nvarchar(4000)
  1360.     declare @command2 nvarchar(4000)
  1361.     declare @command3 nvarchar(4000)
  1362.     declare @command4 nvarchar(4000)
  1363.     declare @inscommand nvarchar(2000)
  1364.     declare @tablenick int    
  1365.     declare @nickname int
  1366.     declare @viewcols int
  1367.     declare @trigname sysname
  1368.     declare @ext nvarchar(10)
  1369.     declare @gstr sysname
  1370.     declare @tablenickchar nvarchar(11)
  1371.     declare @ccols int
  1372.     declare @guidstr    nvarchar(32)
  1373.     declare @colid smallint
  1374.     declare @colordinal        smallint
  1375.     declare @colordstr        varchar(4)
  1376.  
  1377.     declare @colname     sysname
  1378.     declare @cur_name    sysname
  1379.     declare @colpat nvarchar(130)
  1380.     declare @colchar nvarchar(5)
  1381.     declare @piece nvarchar(400)
  1382.  
  1383.     declare @retcode int
  1384.     declare @ifcol nvarchar(4000)
  1385.     declare @ccolchar nvarchar(5)
  1386.     declare @partchangecnt int
  1387.     declare @joinchangecnt int
  1388.     declare @partchangecnt2 int
  1389.     declare @cvstr1    nvarchar(500)
  1390.     declare @cvstr2 nvarchar(500)
  1391.     declare @flag smallint
  1392.     declare @missingbm varbinary(500)
  1393.     declare @missing_cols    varbinary(32)
  1394.     declare @mapdownbm varbinary(500)
  1395.     declare @mapupbm   varbinary(500)
  1396.     declare @missingcolid int
  1397.     declare @maxcolid int
  1398.     declare @missingbmstr varchar(1000)
  1399.     declare @mapdownbmstr varchar(1000)
  1400.     declare @mapupbmstr   varchar(1000)
  1401.     declare @objid int
  1402.     declare @sync_objid int
  1403.     declare @partchbm varbinary(500)
  1404.     declare @missing_col_count    int
  1405.     declare @excluded_col_count int
  1406.     declare @joinchbm varbinary(500)
  1407.     declare @partchstr varchar(1002)
  1408.     declare @joinchstr varchar(1002)
  1409.     declare @column_hole bit
  1410.     declare @notforrepl_bit bit
  1411.     declare @notforrepl_str nvarchar(200)
  1412.     declare @owner_is_admin bit
  1413.     
  1414.     set @notforrepl_bit = 1
  1415.     set @ifcol = ''
  1416.     set @column_hole = 0
  1417.     set @owner_is_admin = 0
  1418.     
  1419.     select @owner_is_admin=sysadmin from master..syslogins l, sysusers u where l.sid=u.sid and u.name=@owner collate database_default
  1420.     select @flag = 0
  1421.     set @objid = OBJECT_ID(@source_table)
  1422.     select @sync_objid = sync_objid, @missing_cols = missing_cols, @excluded_col_count = excluded_col_count,
  1423.                                     @missing_col_count=missing_col_count 
  1424.                     from sysmergearticles where artid= @artid and objid=@objid
  1425.     select @ccols =  count(*) from syscolumns where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp'
  1426.     /* Figure out if there are any holes in the colid sequence */
  1427.     select @maxcolid = max(colid) from syscolumns where id = @objid
  1428.     if @ccols <> @maxcolid
  1429.         select @column_hole = 1
  1430.     /*
  1431.     ** adjust the number of columns in the original table by adding up missing columns; in both Pub/Sub sides.
  1432.     */
  1433.     if @missing_col_count>0
  1434.         select @ccols = @ccols + @missing_col_count
  1435.     select @ccolchar = convert(nchar, @ccols)
  1436.     set @colordinal = 0
  1437.     
  1438.     execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
  1439.     if @@ERROR<>0 or @retcode<>0 return (1)
  1440.     set @tablenickchar = convert(nchar, @tablenick)
  1441.     set @joinchbm = 0x0
  1442.     set @partchbm = 0x0
  1443.  
  1444.     -- Check if the update trigger can be made NOT FOR REPLICATION
  1445.     if exists (select * from sysmergearticles 
  1446.                where nickname = @tablenick 
  1447.                and
  1448.                (before_image_objid is not null or
  1449.                 before_view_objid is not null or
  1450.                 datalength (subset_filterclause) > 1
  1451.                ))
  1452.     begin
  1453.         select @notforrepl_bit = 0
  1454.     end
  1455.     else if exists (select * from sysmergesubsetfilters where art_nickname = @tablenick or join_nickname = @tablenick)
  1456.     begin
  1457.         select @notforrepl_bit = 0
  1458.     end
  1459.     else
  1460.     begin
  1461.         select @notforrepl_bit = 1
  1462.     end
  1463.     
  1464.     select @notforrepl_str = ' 
  1465.     if sessionproperty(''replication_agent'') = 1 and (select trigger_nestlevel()) = 1 -- and master.dbo.fn_isreplmergeagent() = 1
  1466.         return '
  1467.         
  1468.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, colid from syscolumns where
  1469.         id = @objid  and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid
  1470.     FOR READ ONLY
  1471.     
  1472.     /* Try to set the ifcol pieces of the trigger */
  1473.     open col_cursor
  1474.     fetch next from col_cursor into @colname, @colid
  1475.     while (@@fetch_status <> -1)
  1476.         begin
  1477.         set @colordinal = @colordinal + 1
  1478.         set @colpat = '%' + @colname + '%'
  1479.         /* Don't let them update the rowguid column */
  1480.         if columnproperty( @objid, @colname , 'isrowguidcol')=1
  1481.             set @ifcol = 'if update(' + QUOTENAME(@colname) +    ')
  1482.             begin
  1483.             if @@trancount > 0
  1484.                 rollback tran
  1485.                 
  1486.             RAISERROR (20062, 16, -1)
  1487.             end
  1488.                 '
  1489.         /* does updating this column change membership in a partial replica? */
  1490.         select @partchangecnt = count(*) from sysmergearticles 
  1491.             where nickname = @tablenick and subset_filterclause like @colpat
  1492.         select @partchangecnt2 = count(*) from sysmergesubsetfilters
  1493.             where art_nickname = @tablenick and join_filterclause like @colpat
  1494.         select @joinchangecnt = count(*) from sysmergesubsetfilters
  1495.              where join_nickname = @tablenick and join_filterclause like @colpat
  1496.         if @partchangecnt > 0 or @partchangecnt2 > 0
  1497.             exec dbo.sp_MSsetbit @partchbm out, @colid
  1498.         else if @joinchangecnt > 0
  1499.             exec dbo.sp_MSsetbit @joinchbm out, @colid
  1500.         /* Repeat the loop with next column */
  1501.         fetch next from col_cursor into @colname, @colid
  1502.         end
  1503.     close col_cursor
  1504.     deallocate col_cursor
  1505.  
  1506.     -- Initialize string for inserting to before_image table
  1507.     exec sp_MSgetbeforetableinsert @objid, @inscommand output
  1508.  
  1509.     /* Make strings to initialize variables for partchange, joinchange bitmaps */
  1510.     exec master..xp_varbintohexstr @partchbm, @partchstr out
  1511.     exec master..xp_varbintohexstr @joinchbm, @joinchstr out
  1512.  
  1513.     select @mapdownbm =0x00
  1514.     select @mapupbm = 0x00
  1515.     /*
  1516.     ** To see if there is a need for map down.
  1517.     */
  1518.     if @column_hole<>0
  1519.     begin
  1520.         set @missingcolid = 1
  1521.         while (@missingcolid <= @maxcolid)
  1522.             begin
  1523.             if not exists (select * from syscolumns where colid = @missingcolid and
  1524.                         id = OBJECT_ID(@source_table) and iscomputed <> 1 and type_name(xtype) <> 'timestamp')
  1525.                     exec dbo.sp_MSsetbit @mapdownbm out, @missingcolid
  1526.             set @missingcolid = @missingcolid + 1
  1527.             end
  1528.     end
  1529.     set @mapupbm = @missing_cols -- do this at both sides, good for republishing.
  1530.     
  1531.     exec master..xp_varbintohexstr @mapdownbm, @mapdownbmstr out
  1532.     exec master..xp_varbintohexstr @mapupbm, @mapupbmstr out
  1533.     
  1534.     execute @retcode=sp_MSgetreplnick @nickname = @nickname output
  1535.     if @retcode<>0 or @@error<>0 return (1)
  1536.     set @ext = 'upd_'
  1537.  
  1538.     exec @retcode=sp_MSguidtostr @artid, @guidstr out
  1539.     if @retcode<>0 or @@error<>0 return (1)
  1540.  
  1541.     set @trigname =  @ext + @guidstr 
  1542.  
  1543.     /* Make sure trigger name is unique */
  1544.     exec @retcode=sp_MSuniqueobjectname @trigname, @trigname output
  1545.     if @retcode<>0 or @@error<>0 return (1)
  1546.     if @column_tracking <> 0
  1547.         begin
  1548.         /* Set cv pieces appropriately */
  1549.         set @cvstr1 = ' 
  1550.             set @lineage = { fn UPDATELINEAGE(0x0, @nick, @oldmaxversion+1) }
  1551.             set @cv = { fn INITCOLVS(@ccols, @nick) }
  1552.             if (@@error <> 0)
  1553.                 begin
  1554.                 goto FAILURE
  1555.                 end
  1556.             set @cv = { fn UPDATECOLVBM(@cv, @nick, @bm, @missingbm, { fn GETMAXVERSION(@lineage) }) }
  1557.         '
  1558.         set @cvstr2 = '
  1559.                 colv1 = { fn UPDATECOLVBM(colv1, @nick, @bm, @missingbm, { fn GETMAXVERSION({ fn UPDATELINEAGE(lineage, @nick, @oldmaxversion+1) }) }) } '
  1560.         end
  1561.     else
  1562.         begin
  1563.         set @cvstr1 = '   set @lineage = { fn UPDATELINEAGE(0x0, @nick, @oldmaxversion+1) }
  1564.             set @cv = NULL
  1565.      '
  1566.         set @cvstr2 = ' colv1 = NULL '
  1567.         end
  1568.     /* UNDONE maybe remove null guid checks in SQL SERVER 7.0 */
  1569.     select @command1 = 'create trigger ' + @trigname + ' on ' + @source_table +
  1570.     ' FOR UPDATE AS '
  1571.  
  1572.     if (@notforrepl_bit = 1)
  1573.         select @command1 = @command1 + @notforrepl_str
  1574.  
  1575.     select @command1 = @command1 + ' 
  1576.     /* Declare variables */
  1577.  
  1578.     declare @article_rows_updated int
  1579.     select @article_rows_updated = count(*) from inserted
  1580.     declare @contents_rows_updated int, @updateerror int
  1581.     declare @bm varbinary(500), @missingbm varbinary(500), @lineage varbinary(255), @cv varbinary(2048)
  1582.     declare @tablenick int, @nick int, @ccols int, @partchange int, @joinchange int
  1583.     declare    @partchangebm varbinary(500), @joinchangebm varbinary(500)
  1584.     declare @oldmaxversion int
  1585.         
  1586.     set nocount on
  1587.     set @tablenick = ' + @tablenickchar + '
  1588.     select @oldmaxversion= maxversion_at_cleanup from sysmergearticles where nickname = @tablenick
  1589.     
  1590.     /* Use intrinsic funtion to set bits for updated columns */
  1591.     set @bm = columns_updated()
  1592.  
  1593.     /* only do the map down when needed */
  1594.     set @missingbm = ' 
  1595.  
  1596.     select @command2 = '  
  1597.  
  1598.     /* See if the partition might have changed */
  1599.     if @partchangebm = 0x0
  1600.         set @partchange = 0
  1601.     else
  1602.         set @partchange= { fn INTERSECTBITMAPS (@bm, @partchangebm) }
  1603.     
  1604.     /* See if a column used in a join filter changed */
  1605.     if @joinchangebm = 0x0
  1606.         set @joinchange = 0
  1607.     else
  1608.         set @joinchange= { fn INTERSECTBITMAPS (@bm, @joinchangebm) }
  1609.     '
  1610.  
  1611.     if @mapdownbm<>0x00
  1612.         select @command2 = @command2 + 
  1613.                 ' execute master..xp_mapdown_bitmap ' + @mapdownbmstr +', @bm output '
  1614.  
  1615.     select @command2 = @command2 + '
  1616.  
  1617.     exec dbo.sp_MSgetreplnick @nickname = @nick output
  1618.     select @ccols = ' + @ccolchar + '
  1619.     ' + @cvstr1 + '
  1620.         ' 
  1621.     set @command3 = '
  1622.  
  1623.     update ' + @viewname + ' 
  1624.     set lineage = { fn UPDATELINEAGE(lineage, @nick, @oldmaxversion+1) }, 
  1625.         generation = A.gen_cur, 
  1626.         joinchangegen = case when (@joinchange = 1) then A.gen_cur else joinchangegen end, 
  1627.         partchangegen = case when (@partchange = 1) then A.gen_cur else partchangegen end, 
  1628.         ' + @cvstr2 + ' 
  1629.     FROM inserted as I JOIN ' + @viewname + ' as V 
  1630.     ON (I.rowguidcol=V.rowguid)
  1631.     and V.tablenick = @tablenick
  1632.     JOIN (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as A
  1633.     ON V.tablenick = A.nickname
  1634.  
  1635.     select @updateerror = @@error, @contents_rows_updated = @@rowcount
  1636.      ' + case when @inscommand is null or @inscommand = ' ' then ' ' else ' if @joinchange = 1 or @partchange = 1 ' + @inscommand end + ' 
  1637.     if @article_rows_updated <> @contents_rows_updated
  1638.     begin
  1639.  
  1640.         insert into ' + @viewname + ' (tablenick, rowguid, lineage, colv1, generation, partchangegen, joinchangegen) 
  1641.             select @tablenick, rowguidcol, @lineage, @cv, A.gen_cur, 
  1642.             case when (@joinchange = 1 or @partchange = 1) then A.gen_cur else NULL end, 
  1643.             case when @joinchange = 1 then A.gen_cur else NULL end
  1644.             from inserted,
  1645.             (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as A
  1646.             where rowguidcol not in (select rowguid from ' + @viewname + ' where tablenick = @tablenick)
  1647.  
  1648.         if @@error <> 0
  1649.             GOTO FAILURE
  1650.     end
  1651.  
  1652.  
  1653.     return
  1654. FAILURE:
  1655.                 if @@trancount > 0
  1656.                     rollback tran
  1657.                 raiserror (20041, 16, -1)
  1658.                 return
  1659.                     '
  1660.             
  1661.     execute (@command1 + @mapupbmstr + '
  1662.         set @partchangebm = ' + @partchstr + '
  1663.         set @joinchangebm = ' + @joinchstr + '
  1664.             ' + @ifcol +  
  1665.             @command2 + @command3)
  1666.     if @@ERROR <> 0 
  1667.         begin
  1668.             raiserror(20064, 16, -1)
  1669.             return (1)
  1670.         end
  1671.     
  1672.     select @command4 = 'sp_MS_marksystemobject ''' + REPLACE(@owner, '''', '''''') + '.' + @trigname + ''''
  1673.     if @owner_is_admin=1
  1674.         execute (@command4)        
  1675. GO
  1676.  
  1677. exec dbo.sp_MS_marksystemobject sp_MSaddupdatetrigger
  1678. go
  1679.  
  1680. raiserror('Creating procedure sp_MSaddmergetriggers', 0,1)
  1681. GO
  1682. CREATE PROCEDURE sp_MSaddmergetriggers 
  1683.     @source_table         nvarchar(270),                /* was type varchar(92), table name */
  1684.     @table_owner        sysname = NULL,
  1685.     @column_tracking     int = NULL                /* Is column tracking on - default is FALSE */
  1686. AS
  1687.     set nocount on
  1688.     declare @command        nvarchar(4000)
  1689.     declare @command2 nvarchar(4000)
  1690.     declare @inscommand nvarchar(2000)
  1691.     declare @ifcoltracking     nvarchar(255)
  1692.     declare @tablenick         int    
  1693.     declare @nickname         int
  1694.     declare @artid             uniqueidentifier
  1695.     declare @guidstr        nvarchar(32)
  1696.     declare @owner             sysname
  1697.     declare @site             sysname
  1698.     declare @db             sysname
  1699.     declare @object         sysname
  1700.     declare @updtrigname         sysname
  1701.     declare @instrigname         sysname
  1702.     declare @deltrigname         sysname
  1703.     declare @ext                 nvarchar(10)
  1704.     declare @ext2                 nvarchar(10)
  1705.     declare @tablenickchar         nvarchar(11)
  1706.     declare @missing_col_count    int
  1707.     declare @ccols             int
  1708.     declare @ccolchar         nvarchar(5)
  1709.     declare @retcode         int
  1710.     declare @objid            int
  1711.     declare @bitmap         varbinary(40)
  1712.     declare @missing_count    int
  1713.     declare @viewname        sysname
  1714.     declare @tsview            sysname
  1715.     declare @sync_objid        int
  1716.     declare @command3       nvarchar(4000)
  1717.     declare @notforrepl_str    nvarchar(200)
  1718.     declare @notforrepl_bit bit
  1719.     declare @owner_is_admin bit
  1720.     
  1721.     set @notforrepl_bit = 1
  1722.     set @owner_is_admin = 0
  1723.     set @bitmap = 0x0
  1724.     set @missing_count = 0
  1725.  
  1726.     -- PARSENAME VARS
  1727.     declare      @UnqualName      sysname  --rightmost name node
  1728.     declare      @QualName1       sysname  
  1729.     -- END PARSENAME VARS
  1730.  
  1731.     execute @retcode=sp_MSgetreplnick @nickname = @nickname output
  1732.     if @retcode<>0 or @@ERROR<>0 return (1)
  1733.  
  1734.     select @ext = 'ins_'
  1735.     select @ext2 = 'del_'
  1736.     if @table_owner is not NULL
  1737.         select @source_table=QUOTENAME(@table_owner) + '.' + QUOTENAME(@source_table)
  1738.     set @objid =  OBJECT_ID(@source_table)
  1739.  
  1740.     -- set up the before image table if one is desired
  1741.     exec dbo.sp_MScreatebeforetable @objid
  1742.  
  1743.     -- Initialize string for inserting to before_image table
  1744.     exec sp_MSgetbeforetableinsert @objid, @inscommand output
  1745.  
  1746.     select @ccols =  count(*) from syscolumns where id = @objid  and iscomputed <> 1 and type_name(xtype) <> 'timestamp'
  1747.     select @missing_col_count=missing_col_count, @sync_objid=sync_objid from sysmergearticles where objid=@objid
  1748.     /*
  1749.     ** increase the # of columns at subscriber side by adding the missing columns
  1750.     ** Note that publisher side also needs to increase this value due to the possible column holes.
  1751.     */
  1752.     select @ccols = @ccols + @missing_col_count
  1753.     select @ccolchar = convert(nchar, @ccols)
  1754.  
  1755.     select @UnqualName = PARSENAME(@source_table, 1)
  1756.     select @QualName1 = PARSENAME(@source_table, 2)
  1757.     if @UnqualName IS NULL
  1758.          return 1
  1759.  
  1760.     if @QualName1 is NULL
  1761.          select @QualName1 = user_name(uid) from sysobjects where id = object_id(@UnqualName)
  1762.  
  1763.     -- fixup for variable length differences.  remove when vars expanded
  1764.     -- to new SQL SERVER 7.0 lengths
  1765.  
  1766.     select @owner = @QualName1
  1767.     select @object = @UnqualName
  1768.  
  1769.     --this is to find out if table owner is a system user
  1770.     select @owner_is_admin=sysadmin from master..syslogins l, sysusers u where l.sid=u.sid and u.name=@owner collate database_default
  1771.         
  1772.     execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
  1773.     if @retcode<>0 or @@ERROR<>0 return (1)
  1774.     select @artid = artid from sysmergearticles 
  1775.         where objid = @objid
  1776.         
  1777.     /* If column tracking wasn't passed in, just figure it out */
  1778.     if @column_tracking is null
  1779.         select @column_tracking = column_tracking from sysmergearticles 
  1780.         where artid = @artid
  1781.         
  1782.     select @tablenickchar = convert(nchar, @tablenick)
  1783.     exec @retcode=sp_MSguidtostr @artid, @guidstr out
  1784.     if @retcode<>0 or @@ERROR<>0 return (1)
  1785.  
  1786.     -- Check if the triggers can be made NOT FOR REPLICATION
  1787.     if exists (select * from sysmergearticles 
  1788.                where nickname = @tablenick 
  1789.                and
  1790.                (before_image_objid is not null or
  1791.                 before_view_objid is not null or
  1792.                 datalength (subset_filterclause) > 1
  1793.                ))
  1794.     begin
  1795.         select @notforrepl_bit = 0
  1796.     end
  1797.     else if exists (select * from sysmergesubsetfilters where art_nickname = @tablenick or join_nickname = @tablenick)
  1798.     begin
  1799.         select @notforrepl_bit = 0
  1800.     end
  1801.     else
  1802.     begin
  1803.         select @notforrepl_bit = 1
  1804.     end
  1805.     
  1806.     select @notforrepl_str = ' 
  1807.     if sessionproperty(''replication_agent'') = 1 and (select trigger_nestlevel()) = 1 -- and master.dbo.fn_isreplmergeagent() = 1
  1808.         return '
  1809.  
  1810.     /* Drop the article's replication triggers if they preexist */
  1811.     exec dbo.sp_MSdroparticletriggers @source_table, @table_owner
  1812.     if @@ERROR <> 0
  1813.         return 1
  1814.     
  1815.     -- owner name removed
  1816.     set @instrigname = @ext + @guidstr 
  1817.     set @deltrigname = @ext2 + @guidstr
  1818.     set @updtrigname = 'upd_' + @guidstr
  1819.     set @viewname = 'ctsv_' + @guidstr
  1820.     set @tsview = 'tsvw_' + @guidstr
  1821.     
  1822.     /* Make sure trigger name is unique */
  1823.     exec @retcode=sp_MSuniqueobjectname @instrigname, @instrigname output
  1824.     if @retcode<>0 or @@ERROR<>0 return (1)
  1825.     exec @retcode=sp_MSuniqueobjectname @deltrigname, @deltrigname output
  1826.     if @retcode<>0 or @@ERROR<>0 return (1)
  1827.     exec @retcode=sp_MSuniqueobjectname @updtrigname, @updtrigname output
  1828.     if @retcode<>0 or @@ERROR<>0 return (1)
  1829.  
  1830.     /* Create the view if it doesn't already exist. */
  1831.     if not exists (select * from sysobjects where type = 'V' and name = @viewname)
  1832.         begin
  1833.  
  1834.         exec @retcode=sp_MSuniqueobjectname @viewname, @viewname output
  1835.         if @retcode<>0 or @@ERROR<>0 return (1)
  1836.         set @command = 'create view dbo.' + @viewname + ' as
  1837.             select * from dbo.MSmerge_contents where
  1838.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@instrigname) + ''')) > 0 or
  1839.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@updtrigname) + ''')) > 0 or
  1840.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@deltrigname) + ''')) > 0
  1841.                 with check option'
  1842.         execute (@command)
  1843.         if @@ERROR<>0 return (1)
  1844.         set @command = 'grant update, insert, select, delete on ' + @viewname + ' to public'
  1845.         execute (@command)
  1846.         if @@ERROR<>0 return (1)
  1847.         execute ('sp_MS_marksystemobject ''' + @viewname + '''')    
  1848.         if @@ERROR<>0 return (1)    
  1849.         end
  1850.  
  1851.  
  1852.     /* Create the view if it doesn't already exist. */
  1853.     if not exists (select * from sysobjects where type = 'V' and name = @tsview)
  1854.         begin
  1855.         exec @retcode=sp_MSuniqueobjectname @tsview, @tsview output
  1856.         if @retcode<>0 or @@ERROR<>0 return (1)
  1857.         set @command = 'create view dbo. ' + @tsview + ' as
  1858.             select * from dbo.MSmerge_tombstone where
  1859.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@instrigname) + ''')) > 0 or
  1860.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@updtrigname) + ''')) > 0 or
  1861.                 trigger_nestlevel(OBJECT_ID(''' + QUOTENAME(REPLACE(@owner, '''', '''''')) + '.'  + QUOTENAME(@deltrigname) + ''')) > 0
  1862.                 with check option'
  1863.         execute (@command)
  1864.         if @@ERROR<>0 return (1)
  1865.         set @command = 'grant update, insert, select, delete on ' + @tsview + ' to public'
  1866.         execute (@command)
  1867.         if @@ERROR<>0 return (1)        
  1868.         execute ('sp_MS_marksystemobject ''' + @tsview + '''')    
  1869.         if @@ERROR<>0 return (1)    
  1870.         end
  1871.         
  1872.     /* If column tracking is on, construct the string to initialize colv's */
  1873.     if (@column_tracking <> 0)
  1874.         select @ifcoltracking = '    set @colv1 = { fn INITCOLVS(@ccols, @nickname) }'
  1875.     else
  1876.         select @ifcoltracking = '    set @colv1 = NULL'
  1877.         
  1878.     /* UNDONE maybe remove null guid checks in SQL SERVER 7.0 */
  1879.     select @command = 'create trigger ' + @instrigname + ' on ' + @source_table +
  1880.         ' for insert as ' + @notforrepl_str + ' 
  1881.         /* Declare variables */
  1882.         declare @article_rows_inserted int
  1883.         select @article_rows_inserted = count(*) from inserted
  1884.         declare @tablenick int, @nickname int
  1885.         declare @lineage varbinary(255), @colv1 varbinary(2048)
  1886.         declare @ccols int, @retcode smallint, @version int, @curversion int, @oldmaxversion int
  1887.         
  1888.         set nocount on
  1889.         set @tablenick = ' + @tablenickchar + '
  1890.         select @ccols = ' + @ccolchar + '
  1891.         set @lineage = 0x0
  1892.         set @retcode = 0
  1893.         select @oldmaxversion= maxversion_at_cleanup from sysmergearticles where nickname = @tablenick
  1894.         
  1895.         execute dbo.sp_MSgetreplnick @nickname = @nickname output
  1896.         if (@@error <> 0)
  1897.             begin
  1898.             goto FAILURE
  1899.             end
  1900.         set @lineage = { fn UPDATELINEAGE (0x0, @nickname, 1) }
  1901.         ' + @ifcoltracking + '
  1902.         if (@@error <> 0)
  1903.             begin
  1904.             goto FAILURE
  1905.             end
  1906.  
  1907.         if exists (select ts.rowguid from ' + @tsview + ' ts, inserted i where ts.tablenick = @tablenick and ts.rowguid = i.rowguidcol)
  1908.         begin
  1909.             select @version = max({fn GETMAXVERSION(lineage)}) from ' + @tsview + ' where 
  1910.                 tablenick = @tablenick and rowguid in (select rowguidcol from inserted)
  1911.  
  1912.             if @version is not null
  1913.             begin
  1914.                 -- reset lineage and colv to higher version...
  1915.                 set @curversion = 0
  1916.                 while (@curversion <= @version)
  1917.                 begin
  1918.                     set @lineage = { fn UPDATELINEAGE (@lineage, @nickname, @oldmaxversion+1) }
  1919.                     set @curversion = @curversion + 1
  1920.                 end
  1921.  
  1922.                 if (@colv1 IS NOT NULL)
  1923.                     set @colv1 = { fn UPDATECOLVBM(@colv1, @nickname, 0x01, 0x00, { fn GETMAXVERSION(@lineage) }) }
  1924.                 
  1925.                 delete from ' + @tsview + ' where tablenick = @tablenick and rowguid in
  1926.                     (select rowguidcol from inserted)
  1927.             end
  1928.         end
  1929.  
  1930.         if (@article_rows_inserted = 1)
  1931.         begin
  1932.             if not exists (select ct.rowguid from ' + @viewname + ' ct, inserted i where ct.tablenick = @tablenick and ct.rowguid = i.rowguidcol)
  1933.             begin
  1934.                 insert into ' + @viewname + ' (tablenick, rowguid, lineage, colv1, generation, joinchangegen) select
  1935.                     @tablenick, rowguidcol, @lineage, @colv1, A.gen_cur, A.gen_cur from inserted,
  1936.                 (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as A
  1937.             end
  1938.         end
  1939.         else
  1940.         begin
  1941.             insert into ' + @viewname + ' (tablenick, rowguid, lineage, colv1, generation, joinchangegen) select
  1942.                 @tablenick, rowguidcol, @lineage, @colv1, A.gen_cur, A.gen_cur from inserted,
  1943.                 (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as A
  1944.                 where rowguidcol not in (select rowguid from ' + @viewname + ' where tablenick = @tablenick)
  1945.         end
  1946.         if @@error <> 0 
  1947.             goto FAILURE
  1948.         return
  1949.     FAILURE:
  1950.  
  1951.                 if @@trancount > 0
  1952.                     rollback tran
  1953.                 raiserror (20041, 16, -1)
  1954.                 return
  1955.                     '
  1956.     execute (@command)
  1957.     if @@ERROR <> 0 
  1958.         begin
  1959.             raiserror(21304, 16, -1, @source_table)
  1960.             return (1)
  1961.         end
  1962.     
  1963.     select @command3 = 'sp_MS_marksystemobject ''' + REPLACE(@owner, '''', '''''') + '.'  + @instrigname + ''''
  1964.     if @owner_is_admin = 1
  1965.         execute (@command3)    
  1966.     /* Call separate routine to add update trigger */
  1967.     exec @retcode=sp_MSaddupdatetrigger @source_table, @owner, @object, @artid, @column_tracking, @viewname
  1968.     if @retcode<>0 or @@ERROR<>0 return (1)
  1969.  
  1970.     /* Now make the delete trigger */
  1971.     -- NOTE: owner name removed
  1972.  
  1973.     /* Make sure trigger name is unique */
  1974.     exec @retcode = dbo.sp_MSuniqueobjectname @deltrigname, @deltrigname output
  1975.     if @retcode<>0 or @@ERROR<>0 return (1)
  1976.  
  1977.     set @command = 'create trigger ' + @deltrigname + ' on ' + @source_table +
  1978.     ' FOR DELETE AS '
  1979.  
  1980.     if (@notforrepl_bit = 1)
  1981.         select @command = @command + @notforrepl_str
  1982.  
  1983.     select @command = @command + '
  1984.     /* Declare variables */
  1985.     declare @tablenick int, @retcode smallint, @reason nvarchar(255), @nickname int, @lineage varbinary(255), @oldmaxversion int
  1986.     
  1987.     set nocount on
  1988.     select @tablenick = ' + @tablenickchar + '
  1989.     select @oldmaxversion= maxversion_at_cleanup from sysmergearticles where nickname = @tablenick
  1990.     
  1991.     select @reason = ''user delete''
  1992.     execute dbo.sp_MSgetreplnick @nickname = @nickname output
  1993.     if (@@error <> 0)
  1994.         begin
  1995.         goto FAILURE
  1996.         end
  1997.     '
  1998.     set @command2 = '
  1999.     set @lineage = { fn UPDATELINEAGE(0x0, @nickname, @oldmaxversion) }
  2000.  
  2001.     insert into ' + @tsview + ' (rowguid, tablenick, type, lineage, generation, reason)
  2002.         select rowguidcol, @tablenick, 1, { fn UPDATELINEAGE(COALESCE(c.lineage, @lineage), @nickname, @oldmaxversion+1) }, a.gen_cur, @reason from 
  2003.             deleted d left outer join ' + @viewname + ' c on c.tablenick = @tablenick and c.rowguid = d.rowguidcol
  2004.             join (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as a on a.nickname = @tablenick
  2005.     if @@error <> 0
  2006.         GOTO FAILURE
  2007.  
  2008.     delete from ' + @viewname + ' where tablenick = @tablenick and rowguid in 
  2009.         (select rowguidcol from deleted) 
  2010.     if @@error <> 0
  2011.         GOTO FAILURE
  2012.  
  2013.     
  2014.     return
  2015. FAILURE:
  2016.                 if @@trancount > 0
  2017.                     rollback tran
  2018.                 raiserror (20041, 16, -1)
  2019.                 return
  2020.                 '
  2021.     
  2022.     execute (@command + @inscommand + @command2)
  2023.  
  2024.     if @@ERROR <> 0 
  2025.         begin
  2026.             raiserror(21304, 16, -1, @source_table)
  2027.             return (1)
  2028.         end
  2029.     select @command3 = 'sp_MS_marksystemobject ''' + REPLACE(@owner, '''', '''''') + '.' + @deltrigname + ''''
  2030.     if @owner_is_admin = 1
  2031.         execute (@command3)    
  2032.  
  2033.     return (0)
  2034. GO
  2035.  
  2036. exec dbo.sp_MS_marksystemobject sp_MSaddmergetriggers 
  2037. go
  2038. grant exec on dbo.sp_MSaddmergetriggers to public
  2039. go
  2040.  
  2041. raiserror('Creating procedure sp_MShelpdestowner', 0,1)
  2042. GO
  2043.  
  2044. create procedure sp_MSchangeobjectowner(
  2045.     @tablename sysname,
  2046.     @dest_owner    sysname
  2047. )AS
  2048.     declare @uid         smallint
  2049.     declare @retcode    int
  2050.     
  2051.     select @uid=uid from sysobjects where name=@tablename
  2052.  
  2053.     --do not bother to call sp_changeobjectowner the object is owned by the @dest_owner itself
  2054.     if user_name(@uid)=@dest_owner
  2055.         return(0)
  2056.     exec @retcode=sp_changeobjectowner @tablename, @dest_owner
  2057.     if @@ERROR<>0 or @retcode<>0
  2058.     begin
  2059.         raiserror(21346, 16, -1, @tablename, @dest_owner)
  2060.         return (1)
  2061.     end
  2062.     return(0)    
  2063. go
  2064. exec dbo.sp_MS_marksystemobject sp_MSchangeobjectowner 
  2065. go
  2066. grant exec on dbo.sp_MSchangeobjectowner to public
  2067. go
  2068.  
  2069. create procedure sp_MShelpdestowner(
  2070. @spname sysname
  2071. )
  2072. AS
  2073. declare @comment nvarchar(400)
  2074. declare @patindex int
  2075. declare @has_destowner    int
  2076. select @comment = convert(nvarchar(400), text) from syscomments where id = object_id(@spname)
  2077. select @patindex = PATINDEX('%@destowner%', @comment)
  2078. if @patindex<>0
  2079.     select 1
  2080. else
  2081.     select 0
  2082. GO
  2083. exec dbo.sp_MS_marksystemobject sp_MShelpdestowner 
  2084. go
  2085. grant exec on dbo.sp_MShelpdestowner to public
  2086. go
  2087.  
  2088.  
  2089. raiserror('Creating procedure sp_MSfillupmissingcols', 0,1)
  2090. GO
  2091.  
  2092. create procedure sp_MSfillupmissingcols(@publication sysname, @source_table sysname)
  2093. AS
  2094. declare @sync_objid         int
  2095. declare @columns            varbinary(125)
  2096. declare @missingcolid        int
  2097. declare @missingbm            varbinary(125)
  2098. declare @excludedcolid        int
  2099. declare @excludedbm            varbinary(125)
  2100. declare @excludedcolcnt        int
  2101. declare @missingcolcnt        int
  2102. declare @maxcolid            int
  2103. declare @column_tracking    bit
  2104. declare @id                    int
  2105. declare @pubid                uniqueidentifier
  2106. declare @missingindex        int
  2107.  
  2108. select @id = object_id(@source_table)
  2109. select @missingcolcnt = 0
  2110. select @excludedcolcnt = 0
  2111. select @pubid=pubid from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name()
  2112. select @columns = columns, @sync_objid=sync_objid from sysmergearticles where objid = @id and pubid=@pubid
  2113. select @missingbm = 0x00
  2114. select @excludedbm = 0x00
  2115. select @missingcolid = 1 --instead of using the minimal colid in syscolumns with the same id, as we used to do 
  2116. select TOP 1 @maxcolid = colid from syscolumns where id=@id order by colid DESC
  2117.  
  2118. while (@missingcolid <= @maxcolid)
  2119.     begin
  2120.     if exists (select * from syscolumns where colid = @missingcolid and id = @id and 
  2121.                 name not in (select name from syscolumns where id = @sync_objid))
  2122.         begin
  2123.         select @excludedcolcnt = @excludedcolcnt + 1
  2124.         select @missingindex = count(*) from syscolumns where id=@id and colid<=@missingcolid
  2125.         exec dbo.sp_MSsetbit @excludedbm OUTPUT, @missingindex
  2126.         end
  2127.     set @missingcolid = @missingcolid + 1
  2128.     end
  2129.  
  2130. UPDATE sysmergearticles set excluded_col_count = @excludedcolcnt, 
  2131.                             excluded_cols = @excludedbm
  2132.         where objid = @id and pubid=@pubid
  2133. GO
  2134.  
  2135. exec dbo.sp_MS_marksystemobject sp_MSfillupmissingcols 
  2136. go
  2137. grant exec on dbo.sp_MSfillupmissingcols to public
  2138. go
  2139.  
  2140. raiserror('Creating procedure sp_MSmaptype', 0,1)
  2141. GO
  2142.  
  2143. create procedure sp_MSmaptype (@type nvarchar(60) output, 
  2144.                                 @len smallint, 
  2145.                                 @prec int, 
  2146.                                 @scale int)
  2147. as
  2148.     declare @typeout nvarchar(60)
  2149.  
  2150. select @typeout = case @type
  2151.     when 'binary' then 'varbinary'
  2152.     when 'char' then 'varchar'
  2153.     when 'nchar' then 'nvarchar'
  2154.     when 'datetimn' then 'datetime'
  2155.     when 'decimaln' then 'decimal'
  2156.     when 'floatn' then 'float'
  2157.     when 'intn' then 'int'
  2158.     when 'moneyn' then 'money'
  2159.     when 'numericn' then 'numeric'
  2160.     when 'timestamp' then 'varbinary'
  2161.     when 'bit' then 'tinyint'
  2162.     else @type  --for user defined data type which may contain space in between
  2163.     END
  2164. -- append length or scale and precision if needed
  2165. if (@typeout = 'varbinary' or @typeout = 'varchar' or @typeout = 'nvarchar')
  2166.     begin
  2167.     select @type = @typeout + '(' + rtrim(convert(nchar, @len)) + ')'
  2168.     return
  2169.     end
  2170. if (@typeout = 'numeric' or @typeout = 'decimal')
  2171.     begin
  2172.     select @type = @typeout + '(' + rtrim(convert(nchar, @prec)) + ',' + 
  2173.             rtrim(convert(nchar, @scale)) + ')'
  2174.     return
  2175.     end
  2176. select @type = @typeout
  2177. go
  2178.  
  2179. exec dbo.sp_MS_marksystemobject sp_MSmaptype 
  2180. go
  2181.  
  2182. raiserror('Creating procedure sp_MSquerysubtype', 0,1)
  2183. GO
  2184.  
  2185. create procedure sp_MSquerysubtype (@pubid uniqueidentifier,@subscriber sysname, @subscriber_db sysname)
  2186. as
  2187.     declare @subtype    int
  2188.     declare @srvid        int
  2189.  
  2190.     SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  2191.     
  2192.     select @subtype = NULL
  2193.     select @subtype = subscription_type from sysmergesubscriptions where pubid=@pubid 
  2194.         and db_name=@subscriber_db and srvid=@srvid
  2195.     if @subtype is NULL
  2196.         select @subtype=2
  2197.     select @subtype
  2198. go
  2199.  
  2200. exec dbo.sp_MS_marksystemobject sp_MSquerysubtype 
  2201. go
  2202.  
  2203. grant exec on dbo.sp_MSquerysubtype to public
  2204. go
  2205.  
  2206. -- sp_showrowreplicainfo displays row and column version information about a specific row
  2207. -- parameters: 
  2208. --         @ownername: The table owner.
  2209. --        @tablename: Name of the table that contains the row.
  2210. --        @rowguid: Unique identifier of the row of interest.
  2211. --        @show: Determines whether to display row versions, colum versions, or both. Values are 'both', 'row', or 'columns'.
  2212. -- output columns for row version information:
  2213. --        server_name: Name of the server that made this entry
  2214. --        db_name: Name of the database that made this entry.
  2215. --        db_nickname: Nickname of the database that made this entry.
  2216. --        version: Version of the entry.
  2217. --        rowversion_table: Indicates whether lineage is in MSmerge_contents or MSmerge_tombstone.
  2218. --        comment: Records problems with this version entry.
  2219. -- output columns for column version information:
  2220. --        server_name, db_name, db_nickname, version, comment: As above.
  2221. --        colname: Name of the column the colv entry stands for.
  2222. create procedure sp_showrowreplicainfo
  2223.     (@ownername sysname = NULL, @tablename sysname = NULL, @rowguid uniqueidentifier, @show nvarchar(20) = 'both')
  2224. as 
  2225.     set nocount on
  2226.  
  2227.     -- some constants
  2228.     -- this stored proc is for debugging purposes, thus no need for localizing them
  2229.     declare @dbname sysname
  2230.     select @dbname= db_name()
  2231.  
  2232.     declare @missingcolname sysname
  2233.     set @missingcolname= '<Missing column>'
  2234.  
  2235.     declare @anonymousname sysname
  2236.     set @anonymousname= '<Anonymous subscriber>'
  2237.  
  2238.     declare @unknownname sysname
  2239.     set @unknownname= '<Unknown server name>'
  2240.  
  2241.     declare @mergename sysname
  2242.     set @mergename= '<Merge nickname>'
  2243.  
  2244.     declare @nondecreasingversion nvarchar(128)
  2245.     set @nondecreasingversion= 'Problem found: Non-decreasing version.'
  2246.  
  2247.     declare @toohighcolvversion nvarchar(128)
  2248.     set @toohighcolvversion= 'Problem found: Version is higher than highest version in lineage.'
  2249.  
  2250.     declare @naname sysname
  2251.     set @naname= '<n/a>'
  2252.  
  2253.     if @tablename is NULL
  2254.     begin
  2255.         set @tablename= (select top 1 object_name(objid) from sysmergearticles where 
  2256.                             nickname = (select tablenick from MSmerge_contents where rowguid = @rowguid))
  2257.     end
  2258.  
  2259.     if @tablename is NULL
  2260.     begin
  2261.         set @tablename= (select top 1 object_name(objid) from sysmergearticles where 
  2262.                             nickname = (select tablenick from MSmerge_tombstone where rowguid = @rowguid))
  2263.     end
  2264.  
  2265.     -- check whether given table exists
  2266.     if not exists (select * from sysobjects where xtype = 'U' and name = @tablename)
  2267.     begin
  2268.         raiserror (20507, 16, 1, @tablename, @dbname)
  2269.         return 1
  2270.     end
  2271.     else if @ownername is not null
  2272.     begin
  2273.         -- check whether table belongs to the given owner
  2274.         if not exists (select * from sysobjects where xtype = 'U' and name=@tablename and uid = (select uid from sysusers where name = @ownername))
  2275.         begin
  2276.             declare @qualifiedtablename nvarchar(257)
  2277.             select @qualifiedtablename= @ownername + '.' + @dbname
  2278.             raiserror (20507, 16, 1, @qualifiedtablename, @dbname)
  2279.             return 1
  2280.         end
  2281.     end
  2282.  
  2283.     -- get tableid and tablenick from tablename
  2284.     declare @tableid int
  2285.     declare @tablenick int
  2286.     set @tableid= object_id(@tablename)
  2287.     select @tablenick = (select top 1 nickname from sysmergearticles where objid = @tableid)
  2288.     if @tablenick is null
  2289.     begin
  2290.         raiserror (20027, 16, 1, @tablename)
  2291.         return 1
  2292.     end
  2293.  
  2294.     -- check whether there is an entry for this row in either MSmerge_contents or MSmerge_tombstone
  2295.     declare @incontents int
  2296.     declare @lineage varbinary(249)
  2297.     select @lineage= lineage from MSmerge_contents where rowguid = @rowguid
  2298.     if @lineage is not null
  2299.     begin
  2300.         set @incontents= 1
  2301.     end
  2302.     else
  2303.     begin
  2304.         select @lineage= lineage from MSmerge_tombstone where rowguid = @rowguid
  2305.         if @lineage is not null
  2306.         begin
  2307.             set @incontents= 0
  2308.         end
  2309.         else
  2310.         begin
  2311.             raiserror(21511,10,1)
  2312.             return 0
  2313.         end
  2314.     end
  2315.  
  2316.     -- create temporary table for information about lineage and colv entries
  2317.     create table #results (type nchar(7) null, rowversion_table nchar(17) null, server_name sysname null, 
  2318.                             [db_name] sysname null,  db_nickname int not null, colid int null, colname sysname null, 
  2319.                             version int not null, comment nvarchar(255) null, id int identity(1,1) not null) 
  2320.     
  2321.     if lower(@show collate SQL_Latin1_General_CP1_CS_AS) in ('both', 'row')
  2322.     begin
  2323.         -- insert lineage information into temptable
  2324.         insert into #results (db_nickname, version) exec master..xp_showlineage @lineage
  2325.         update #results set type= 'lineage'
  2326.         if (@incontents = 1)
  2327.         begin
  2328.             update #results set rowversion_table = 'MSmerge_contents'
  2329.         end
  2330.         else
  2331.         begin
  2332.             update #results set rowversion_table = 'MSmerge_tombstone'
  2333.         end
  2334.     end
  2335.  
  2336.     if (@incontents = 1) and (lower(@show collate SQL_Latin1_General_CP1_CS_AS) in ('both', 'columns'))
  2337.     begin
  2338.         -- insert colv information into temptable
  2339.         declare @colv varbinary(2048)
  2340.         select @colv= colv1 from MSmerge_contents where rowguid=@rowguid
  2341.         if @colv is not null
  2342.         begin
  2343.             insert into #results (colid, db_nickname, version) exec master..xp_showcolv @colv
  2344.             update #results set type= 'colv' where type is null
  2345.  
  2346.             -- translate colids into column names
  2347.             if (select top 1 missing_col_count from sysmergearticles where nickname = @tablenick) = 0
  2348.             begin
  2349.                 -- no missing cols: position of entries in colv correspond to colid in sysmergearticles
  2350.                 update #results set colname= s.name from syscolumns s where #results.colid = s.colid and s.id = @tableid
  2351.             end
  2352.             else
  2353.             begin
  2354.                 -- missing cols: colv has entries for columns that do not exist in this db
  2355.                 declare @colname sysname
  2356.                 declare @ismissing int
  2357.                 declare @missingsofar int
  2358.                 declare @colid int
  2359.                 declare @missingcols varbinary(128)
  2360.                 select @missingcols= (select top 1 missing_cols from sysmergearticles where nickname = @tablenick)
  2361.                 set @missingsofar= 0
  2362.                 select @colid= (select min(colid) from #results where colname is null and colid is not null)
  2363.                 while @colid is not null
  2364.                 begin
  2365.                     -- is this column missing?
  2366.                     exec @ismissing= sp_MStestbit @missingcols, @colid
  2367.                     if @ismissing <> 0
  2368.                     begin
  2369.                         update #results set colname= @missingcolname, server_name= @naname, [db_name]= @naname
  2370.                                              where colid = @colid
  2371.                         set @missingsofar= @missingsofar + 1
  2372.                     end
  2373.                     else
  2374.                     begin
  2375.                         select @colname= (select name from syscolumns where id = @tableid and colid = (@colid - @missingsofar))
  2376.                         update #results set colname= @colname where colid = @colid
  2377.                     end
  2378.                     
  2379.                     select @colid= (select min(colid) from #results where colname is null and colid is not null)
  2380.                 end
  2381.             end
  2382.         end
  2383.     end
  2384.  
  2385.     -- transform null comment to empty strings
  2386.     update #results set comment= ''
  2387.  
  2388.     -- translate nicknames in temptable into real db names; set server names, too
  2389.     declare @subid uniqueidentifier
  2390.     declare @servername sysname
  2391.     declare @srvid int
  2392.     declare @replnick int
  2393.  
  2394.     update #results set [db_name]= @mergename, server_name= @naname where db_nickname=1
  2395.  
  2396.     select @replnick= (select top 1 db_nickname from #results where [db_name] is null)
  2397.     while @replnick is not null
  2398.     begin
  2399.         select @subid= (select top 1 s.subid
  2400.                             from sysmergesubscriptions s, MSmerge_replinfo r 
  2401.                             where r.repid = s.subid and @replnick = r.replnickname)
  2402.  
  2403.         select @dbname= (select [db_name] from sysmergesubscriptions where subid = @subid)
  2404.         if @dbname is null
  2405.         begin
  2406.             set @dbname=@anonymousname
  2407.             set @servername= @unknownname
  2408.         end
  2409.         else
  2410.         begin
  2411.             select @servername= (select srv.srvname from master..sysservers srv, sysmergesubscriptions sub
  2412.                             where srv.srvid = sub.srvid and sub.subid = @subid)
  2413.         end
  2414.  
  2415.         update #results set [db_name]= @dbname, server_name= @servername 
  2416.                         where db_nickname = @replnick and [db_name] is null
  2417.         select @replnick= (select top 1 db_nickname from #results where [db_name] is null)
  2418.     end
  2419.  
  2420.     -- record increasing lineage versions
  2421.     update #results set comment= @nondecreasingversion 
  2422.             where type = 'lineage' and 
  2423.             exists (select * from #results r where r.version < #results.version and r.id < #results.id)
  2424.  
  2425.     -- record colv versions that are higher than highest lineage version
  2426.     update #results set comment= @toohighcolvversion 
  2427.             where type = 'colv' and 
  2428.             not exists (select version from #results r where type = 'lineage' and r.version >= #results.version)
  2429.     
  2430.     -- deliver results
  2431.     if lower(@show collate SQL_Latin1_General_CP1_CS_AS) in ('both', 'row')
  2432.     begin
  2433.         select server_name, [db_name], db_nickname, version, rowversion_table, comment from #results where type = 'lineage' order by id
  2434.     end
  2435.  
  2436.     if lower(@show collate SQL_Latin1_General_CP1_CS_AS) in ('both', 'columns')
  2437.     begin
  2438.         select server_name, db_name, db_nickname, version, colname, comment from #results where type = 'colv' order by id
  2439.     end
  2440.  
  2441.     drop table #results
  2442.     return 0
  2443. go
  2444. exec dbo.sp_MS_marksystemobject sp_showrowreplicainfo
  2445. go
  2446. grant execute on dbo.sp_showrowreplicainfo to public
  2447. go
  2448.  
  2449.  
  2450. create procedure sp_MSsethighestversion (@artnick int)
  2451. as
  2452.     set nocount on
  2453.     declare @minlineagelength int
  2454.     set @minlineagelength= 8
  2455.  
  2456.     declare @maxversion int
  2457.     declare @maxversiontombstone int
  2458.  
  2459.     set @maxversion= (select max({fn GETMAXVERSION(mc.lineage)}) 
  2460.             from MSmerge_contents as mc inner join #oldgens as og on (mc.generation = og.gen) where
  2461.                 tablenick = @artnick and
  2462.                 lineage is not null and
  2463.                 datalength(lineage) >= @minlineagelength)
  2464.     if @@error<>0 goto Failure
  2465.  
  2466.     set @maxversiontombstone= (select max({fn GETMAXVERSION(mt.lineage)}) 
  2467.             from MSmerge_tombstone as mt inner join #oldgens as og on (mt.generation = og.gen) where
  2468.                 tablenick = @artnick and
  2469.                 lineage is not null and
  2470.                 datalength(lineage) >= @minlineagelength)
  2471.     if @@error<>0 goto Failure
  2472.  
  2473.     if @maxversion is null
  2474.     begin
  2475.         set @maxversion= @maxversiontombstone
  2476.     end
  2477.  
  2478.     if @maxversiontombstone is not null and @maxversiontombstone > @maxversion
  2479.     begin
  2480.         set @maxversion= @maxversiontombstone
  2481.     end
  2482.  
  2483.     if @maxversion is not null
  2484.     begin
  2485.         update sysmergearticles set maxversion_at_cleanup= @maxversion where
  2486.             nickname = @artnick and
  2487.             maxversion_at_cleanup < @maxversion
  2488.         if @@error<>0 goto Failure
  2489.     end
  2490.  
  2491.     return 0
  2492.  
  2493. Failure:
  2494.     return 1
  2495. go
  2496. exec dbo.sp_MS_marksystemobject sp_MSsethighestversion
  2497. go
  2498. grant execute on dbo.sp_MSsethighestversion to public
  2499. go
  2500.  
  2501.  
  2502. create procedure sp_mergemetadataretentioncleanup
  2503.     (@num_genhistory_rows int = 0 output, 
  2504.      @num_contents_rows int = 0 output, 
  2505.      @num_tombstone_rows int = 0 output)
  2506. as
  2507.     declare @maxretention int
  2508.     declare @artnick int
  2509.     declare @gen int
  2510.     declare @retcode smallint
  2511.     declare @bi_objid int
  2512.     declare @cmd nvarchar(200)
  2513.     declare @guidnull uniqueidentifier
  2514.     declare @delbatchsize int
  2515.     declare @delcount int
  2516.        declare @applockname nvarchar(255)
  2517.  
  2518.     set @num_genhistory_rows= 0
  2519.     set @num_contents_rows= 0
  2520.     set @num_tombstone_rows= 0
  2521.  
  2522.     -- if somebody else is already cleaning up in this database, we simply return
  2523.        set @applockname= 'MS_sp_mergemetadataretentioncleanup' + convert(nvarchar(11), db_id())
  2524.     exec @retcode= sp_getapplock @Resource= @applockname, @LockMode= 'Exclusive', @LockOwner= 'Session', @LockTimeout= 0 
  2525.     if @@error <> 0 or @retcode < 0 return (0)
  2526.     
  2527.     set @guidnull= '00000000-0000-0000-0000-000000000000'
  2528.     set @delbatchsize= 5000
  2529.  
  2530.     create table #oldgens (gen int unique clustered)
  2531.  
  2532.     -- iterate over all articles that do not belong to a publication with infinite retention
  2533.     declare article_curs cursor local fast_forward for 
  2534.         select distinct nickname from sysmergearticles where 
  2535.             nickname not in (select distinct a.nickname from sysmergearticles as a inner join sysmergepublications as p on (a.pubid = p.pubid) 
  2536.                                 where isnull(p.retention, 0) = 0)
  2537.  
  2538.     open article_curs
  2539.     fetch next from article_curs into @artnick
  2540.  
  2541.     while (@@fetch_status <> -1)
  2542.     begin
  2543.         -- find max retention of all pubs the article belongs to
  2544.         select @maxretention= max(isnull(retention,0)) from sysmergepublications where
  2545.                                 pubid in (select pubid from sysmergearticles where nickname = @artnick)
  2546.         -- add one to make up for maximal possible timezone differences, plus one to compensate for clock inaccuracies
  2547.         set @maxretention= @maxretention + 1
  2548.  
  2549.         delete from #oldgens
  2550.         insert into #oldgens select distinct generation from MSmerge_genhistory where
  2551.                                  art_nick = @artnick and
  2552.                                 guidlocal <> @guidnull and
  2553.                                 coldate < dateadd(day, -@maxretention, getdate())
  2554.  
  2555.         -- go to next article if this one has no stale generations
  2556.         if @@rowcount = 0
  2557.         begin
  2558.             fetch next from article_curs into @artnick
  2559.             continue
  2560.         end
  2561.  
  2562.         -- set highest version in sysmergearticles
  2563.         exec @retcode= sp_MSsethighestversion @artnick= @artnick
  2564.         if @retcode<>0 or @@error<>0 goto Failure
  2565.  
  2566.         -- clean up contents, tombstone, before image (if it exists), genhistory
  2567.         set rowcount @delbatchsize
  2568.         set @delcount= @delbatchsize
  2569.         while @delcount = @delbatchsize
  2570.         begin
  2571.             delete mc from MSmerge_contents as mc inner join #oldgens as og on (mc.generation = og.gen) where mc.tablenick = @artnick
  2572.             set @delcount= @@rowcount
  2573.             set @num_contents_rows= @num_contents_rows + @delcount
  2574.         end
  2575.  
  2576.         set @delcount= @delbatchsize
  2577.         while @delcount = @delbatchsize
  2578.         begin
  2579.             delete mt from MSmerge_tombstone as mt inner join #oldgens as og on (mt.generation = og.gen) where tablenick = @artnick
  2580.             set @delcount= @@rowcount
  2581.             set @num_tombstone_rows= @num_tombstone_rows + @delcount
  2582.         end
  2583.  
  2584.         set @bi_objid= (select top 1 before_image_objid from sysmergearticles where nickname = @artnick)
  2585.         if @bi_objid is not null
  2586.         begin
  2587.             set @cmd= 'delete bi from ' + object_name(@bi_objid) + ' as bi inner join #oldgens as og on (bi.generation = og.gen)'
  2588.             set @delcount= @delbatchsize
  2589.             while @delcount = @delbatchsize
  2590.             begin
  2591.                 exec dbo.sp_executesql @cmd
  2592.                 set @delcount= @@rowcount
  2593.             end
  2594.         end
  2595.  
  2596.         set @delcount= @delbatchsize
  2597.         while @delcount = @delbatchsize
  2598.         begin
  2599.             delete gh from MSmerge_genhistory as gh inner join #oldgens as og on (gh.generation = og.gen) where art_nick = @artnick
  2600.             set @delcount= @@rowcount
  2601.             set @num_genhistory_rows= @num_genhistory_rows + @delcount
  2602.         end
  2603.  
  2604.         set rowcount 0
  2605.  
  2606.         -- get next article
  2607.         fetch next from article_curs into @artnick
  2608.     end
  2609.  
  2610.     close article_curs
  2611.     deallocate article_curs
  2612.     drop table #oldgens
  2613.     
  2614.     exec sp_MScleanup_zeroartnick_genhistory @num_genhistory_rows output, @num_contents_rows output
  2615.      
  2616.     exec @retcode= sp_releaseapplock @Resource= @applockname, @LockOwner= 'Session'
  2617.     if @@error <> 0 or @retcode < 0
  2618.         return (1)
  2619.     else
  2620.         return (0)
  2621.  
  2622. Failure:
  2623.     close article_curs
  2624.     deallocate article_curs
  2625.     drop table #oldgens
  2626.     exec sp_releaseapplock @Resource= @applockname, @LockOwner= 'Session'
  2627.     return (1)
  2628.  
  2629. go
  2630. exec dbo.sp_MS_marksystemobject sp_mergemetadataretentioncleanup
  2631. go
  2632. grant execute on dbo.sp_mergemetadataretentioncleanup to public
  2633. go
  2634.  
  2635. raiserror('Creating procedure sp_MSpurgecontentsorphans', 0,1)
  2636. go
  2637. create procedure sp_MSpurgecontentsorphans
  2638. as
  2639.     declare @retcode smallint
  2640.     
  2641.     create table #oldgens (artnick int, gen int)
  2642.     create unique clustered index ucOldgens on #oldgens(artnick, gen)
  2643.  
  2644.     -- find generations that exist in MSmerge_contents but not in MSmerge_genhistory
  2645.     insert into #oldgens (artnick, gen) select distinct tablenick, generation
  2646.             from dbo.MSmerge_contents
  2647.             where generation not in (select distinct generation from dbo.MSmerge_genhistory)
  2648.             
  2649.     exec @retcode = sp_MSdelete_specifiedcontents
  2650.     drop table #oldgens
  2651.     return @retcode
  2652. go
  2653. exec dbo.sp_MS_marksystemobject sp_MSpurgecontentsorphans
  2654. go
  2655. grant execute on dbo.sp_MSpurgecontentsorphans to public
  2656. go
  2657.  
  2658. raiserror('Creating procedure sp_MScleanup_zeroartnick_genhistory', 0,1)
  2659. go
  2660. create procedure sp_MScleanup_zeroartnick_genhistory 
  2661.     (@num_genhistory_rows int = 0 output, 
  2662.      @num_contents_rows int = 0 output)
  2663. as
  2664.     declare @retcode smallint
  2665.     declare @maxretention int
  2666.     declare @guidnull uniqueidentifier
  2667.     declare @oldgencount int
  2668.     declare @zeroartnickgencount int
  2669.     
  2670.     -- If there is any publication that has infinite retention, then we 
  2671.     -- should not clean up genhistory rows that have 0 art_nick. This is 
  2672.     -- because the gen could potentially have changes in articles that belong
  2673.     -- to that publication.
  2674.     if exists (select * from sysmergepublications where isnull(retention, 0) = 0)
  2675.         return 0
  2676.     
  2677.     -- Now we know we only have publications that have a finite retention period.
  2678.     -- Let us choose the highest retention period across all publications and use
  2679.     -- that when cleaning up generations with 0 art_nick. Again this is because this
  2680.     -- gen could have changes in articles from any of those publications. It is safer
  2681.     -- to be pessimistic.
  2682.     select @maxretention = max(isnull(retention,0)) from sysmergepublications
  2683.     
  2684.     -- add one to make up for maximal possible timezone differences, plus one to compensate for clock inaccuracies
  2685.     set @maxretention= @maxretention + 1
  2686.  
  2687.     create table #oldgens (artnick int, gen int)
  2688.     create unique clustered index ucOldgens on #oldgens(artnick, gen)
  2689.     create table #zeroartnickgens (gen int)
  2690.     create unique clustered index ucZeroartnickgens on #zeroartnickgens(gen)
  2691.     
  2692.     set @guidnull= '00000000-0000-0000-0000-000000000000'
  2693.     
  2694.     insert into #zeroartnickgens (gen) select distinct generation from MSmerge_genhistory where
  2695.                                     art_nick = 0 and
  2696.                                     generation > 1 and
  2697.                                     guidlocal <> @guidnull and
  2698.                                     coldate < dateadd(day, -@maxretention, getdate())
  2699.                                     
  2700.     select @zeroartnickgencount = @@rowcount
  2701.     
  2702.     if (@zeroartnickgencount = 0)
  2703.     begin
  2704.         drop table #oldgens
  2705.         drop table #zeroartnickgens
  2706.         return 0
  2707.     end
  2708.     
  2709.     -- find entries that exist in MSmerge_contents that have art_nick = 0 in MSmerge_genhistory
  2710.     insert into #oldgens (artnick, gen) select distinct tablenick, generation
  2711.             from dbo.MSmerge_contents
  2712.             where generation in (select gen from #zeroartnickgens)
  2713.         
  2714.     select @oldgencount = @@rowcount
  2715.     set @retcode = 0
  2716.     
  2717.     if (@oldgencount > 0)
  2718.     begin
  2719.         exec @retcode = sp_MSdelete_specifiedcontents @num_contents_rows output
  2720.     end
  2721.     
  2722.     if (@@error = 0 and @retcode = 0)
  2723.     begin
  2724.         declare @delcount int
  2725.         declare @delbatchsize int
  2726.         set @delbatchsize= 5000
  2727.  
  2728.         set rowcount @delbatchsize
  2729.         set @delcount= @delbatchsize
  2730.         while @delcount = @delbatchsize
  2731.         begin
  2732.             delete gh from MSmerge_genhistory as gh inner join #zeroartnickgens as zag on (gh.generation = zag.gen) 
  2733.                     where art_nick = 0 
  2734.                     and generation > 1 
  2735.                     and guidlocal <> @guidnull 
  2736.                     and coldate < dateadd(day, -@maxretention, getdate())
  2737.                     
  2738.             set @delcount= @@rowcount
  2739.             set @num_genhistory_rows= @num_genhistory_rows + @delcount
  2740.         end
  2741.  
  2742.         set rowcount 0
  2743.     end
  2744.     
  2745.     drop table #oldgens
  2746.     drop table #zeroartnickgens
  2747.     return @retcode
  2748. go
  2749. exec dbo.sp_MS_marksystemobject sp_MScleanup_zeroartnick_genhistory
  2750. go
  2751. raiserror('Creating procedure sp_MSdelete_specifiedcontents', 0,1)
  2752. go
  2753. create procedure sp_MSdelete_specifiedcontents (@num_contents_rows int = 0 output)
  2754. as
  2755.     declare @retcode smallint
  2756.     -- iterate over articles in the temptable
  2757.     declare @artnick int
  2758.     declare article_curs cursor local fast_forward for 
  2759.         select distinct artnick from #oldgens
  2760.  
  2761.     open article_curs
  2762.     fetch next from article_curs into @artnick
  2763.  
  2764.     while (@@fetch_status <> -1)
  2765.     begin
  2766.         -- if necessary, update highest version in sysmergearticles
  2767.         exec @retcode= sp_MSsethighestversion @artnick= @artnick
  2768.         if @retcode<>0 or @@error<>0 goto Failure
  2769.  
  2770.         -- clean up orphaned rows in MSmerge_contents
  2771.         declare @delcount int
  2772.         declare @delbatchsize int
  2773.         
  2774.         set @delbatchsize= 5000
  2775.         set rowcount @delbatchsize
  2776.         set @delcount= @delbatchsize
  2777.         while @delcount = @delbatchsize
  2778.         begin
  2779.             delete mc from MSmerge_contents as mc inner join #oldgens as og 
  2780.                 on (mc.tablenick = og.artnick and mc.generation = og.gen) 
  2781.                 where mc.tablenick = @artnick
  2782.             set @delcount= @@rowcount
  2783.             set @num_contents_rows = @num_contents_rows + @delcount
  2784.         end
  2785.  
  2786.         -- get next article
  2787.         fetch next from article_curs into @artnick
  2788.     end
  2789.     set rowcount 0
  2790.     
  2791.     close article_curs
  2792.     deallocate article_curs
  2793.     return(0)
  2794.  
  2795. Failure:
  2796.     close article_curs
  2797.     deallocate article_curs
  2798.     return (1)
  2799. go
  2800. exec dbo.sp_MS_marksystemobject sp_MSdelete_specifiedcontents
  2801. go
  2802. dump tran master with no_log
  2803. go
  2804.  
  2805. checkpoint
  2806. go
  2807. set nocount on
  2808. go
  2809.  
  2810. execute dbo.sp_configure 'update',1
  2811. go
  2812. reconfigure with override
  2813. go
  2814.  
  2815. set ANSI_NULLS off
  2816. go
  2817.  
  2818. dump tran master with no_log
  2819. go
  2820.  
  2821. use master
  2822. go
  2823.  
  2824. /* 
  2825. ** Drop the stored procedures in this script using the old dropping SP 
  2826. ** and then drop itself
  2827. */
  2828. if exists (select * from sysobjects
  2829.     where type = 'P '
  2830.             and name = 'sp_MSdrop_rladmin')
  2831. begin
  2832.     drop procedure sp_MSdrop_rladmin
  2833. end
  2834.  
  2835. /*
  2836. ** Create stored procedures to drop the stored procedures
  2837. ** created by this script
  2838. */
  2839.  
  2840. raiserror('Creating procedure sp_MSdrop_rladmin', 0,1)
  2841. GO
  2842. create procedure sp_MSdrop_rladmin
  2843. as
  2844.     if exists (select * from sysobjects
  2845.             where type in ('P ') 
  2846.                 and name = 'sp_MSaddmergepub_snapshot')
  2847.         drop procedure sp_MSaddmergepub_snapshot
  2848.  
  2849.     if exists (select * from sysobjects
  2850.             where type in ('P ') 
  2851.                 and name = 'sp_MSremove_userscript')
  2852.         drop procedure sp_MSremove_userscript
  2853.  
  2854.     if exists (select * from sysobjects
  2855.             where type in ('P ') 
  2856.                 and name = 'sp_MSretrieve_mergepublication')
  2857.         drop procedure sp_MSretrieve_mergepublication
  2858.  
  2859.     if exists (select * from sysobjects
  2860.             where type in ('P ') 
  2861.                 and name = 'sp_MSadjustmergeidentity')
  2862.         drop procedure sp_MSadjustmergeidentity
  2863.  
  2864.     if exists (select * from sysobjects
  2865.             where type in ('P ') 
  2866.                 and name = 'sp_MScheckatpublisher')
  2867.         drop procedure sp_MScheckatpublisher    
  2868.     
  2869.     if exists (select * from sysobjects
  2870.             where type in ('P ') 
  2871.                 and name = 'sp_MSdropmergepub_snapshot')
  2872.         drop procedure sp_MSdropmergepub_snapshot
  2873.     
  2874.     if exists (select * from sysobjects
  2875.             where type = 'P'
  2876.                 and name = 'sp_addmergepublication')
  2877.         drop procedure sp_addmergepublication
  2878.  
  2879.     if exists (select * from sysobjects
  2880.         where type = 'P'
  2881.             and name = 'sp_changemergepublication')
  2882.         drop procedure sp_changemergepublication
  2883.  
  2884.     if exists (select * from sysobjects
  2885.         where type = 'P'
  2886.             and name = 'sp_MSCheckmergereplication')
  2887.         drop procedure sp_MSCheckmergereplication
  2888.  
  2889.     if exists (select * from sysobjects
  2890.             where type = 'P'
  2891.                 and name = 'sp_helpmergepublication')
  2892.         drop procedure sp_helpmergepublication
  2893.  
  2894.     if exists (select * from sysobjects
  2895.             where type = 'P'
  2896.                 and name = 'sp_mergearticlecolumn')
  2897.         drop procedure sp_mergearticlecolumn
  2898.  
  2899.     if exists (select * from sysobjects
  2900.             where type = 'P'
  2901.                 and name = 'sp_helpmergearticlecolumn')
  2902.         drop procedure sp_helpmergearticlecolumn
  2903.  
  2904.     if exists (select * from sysobjects
  2905.             where type = 'P'
  2906.                 and name = 'sp_MSpublicationview')
  2907.         drop procedure sp_MSpublicationview
  2908.  
  2909.      if exists (select * from sysobjects
  2910.                 where type = 'P' and
  2911.                 name = 'sp_reinitmergesubscription')
  2912.         drop procedure sp_reinitmergesubscription
  2913.  
  2914.      if exists (select * from sysobjects
  2915.                 where type = 'P' and
  2916.                 name = 'sp_MSreinitmergepublication')
  2917.         drop procedure sp_MSreinitmergepublication
  2918.      
  2919.  
  2920.     if exists (select * from sysobjects
  2921.             where type = 'P'
  2922.                 and name = 'sp_MScleanup_conflict_table')
  2923.         drop procedure sp_MScleanup_conflict_table
  2924.  
  2925.     if exists (select * from sysobjects
  2926.             where type = 'P'
  2927.                 and name = 'sp_MScleanup_conflict')
  2928.         drop procedure sp_MScleanup_conflict
  2929.  
  2930.     if exists (select * from sysobjects
  2931.         where type = 'P'
  2932.             and name = 'sp_MScleanup_metadata')
  2933.         drop procedure sp_MScleanup_metadata
  2934.  
  2935.     if exists (select * from sysobjects
  2936.         where type = 'P'
  2937.             and name = 'sp_mergecleanupmetadata')
  2938.         drop procedure sp_mergecleanupmetadata
  2939.  
  2940.     if exists (select * from sysobjects
  2941.         where type = 'P'
  2942.             and name = 'sp_MSquiescetriggerson')
  2943.         drop procedure sp_MSquiescetriggerson
  2944.  
  2945.     if exists (select * from sysobjects
  2946.         where type = 'P'
  2947.             and name = 'sp_MSquiescecheck')
  2948.         drop procedure sp_MSquiescecheck
  2949.  
  2950.     if exists (select * from sysobjects
  2951.         where type = 'P'
  2952.             and name = 'sp_MSquiescetriggersoff')
  2953.         drop procedure sp_MSquiescetriggersoff
  2954.  
  2955.     if exists (select * from sysobjects
  2956.         where type = 'P'
  2957.             and name = 'sp_helpmergecleanupwait')
  2958.         drop procedure sp_helpmergecleanupwait
  2959.  
  2960.     if exists (select * from sysobjects
  2961.         where type = 'P'
  2962.             and name = 'sp_mergepreparecleanup')
  2963.         drop procedure sp_mergepreparecleanup
  2964.  
  2965.     if exists (select * from sysobjects
  2966.         where type = 'P'
  2967.             and name = 'sp_MSquiesceforcleanup')
  2968.         drop procedure sp_MSquiesceforcleanup
  2969.  
  2970.     if exists (select * from sysobjects
  2971.         where type = 'P'
  2972.             and name = 'sp_mergecompletecleanup')
  2973.         drop procedure sp_mergecompletecleanup
  2974.  
  2975.     if exists (select * from sysobjects
  2976.         where type = 'P'
  2977.             and name = 'sp_MScompletecleanup')
  2978.         drop procedure sp_MScompletecleanup
  2979.  
  2980.     if exists (select * from sysobjects
  2981.         where type = 'P'
  2982.             and name = 'sp_MSpreparecleanup')
  2983.         drop procedure sp_MSpreparecleanup
  2984.  
  2985.     if exists (select * from sysobjects
  2986.             where type = 'P'
  2987.                 and name = 'sp_MSdrop_expired_mergesubscription')
  2988.         drop procedure sp_MSdrop_expired_mergesubscription
  2989.     
  2990.     if exists (select * from sysobjects
  2991.         where type = 'P'
  2992.             and name = 'sp_dropmergepublication')
  2993.         drop procedure sp_dropmergepublication
  2994.     
  2995.     if exists (select * from sysobjects 
  2996.         where type = 'P'
  2997.             and name = 'sp_MSaddmergeschemaarticle')
  2998.         drop procedure sp_MSaddmergeschemaarticle
  2999.  
  3000.     if exists (select * from sysobjects
  3001.             where type = 'P'
  3002.                 and name = 'sp_addmergearticle')
  3003.         drop procedure sp_addmergearticle
  3004.  
  3005.     if exists (select * from sysobjects 
  3006.         where type = 'P'
  3007.             and name = 'sp_MSchangemergeschemaarticle')
  3008.         drop procedure sp_MSchangemergeschemaarticle
  3009.  
  3010.     if exists (select * from sysobjects
  3011.         where type = 'P'
  3012.             and name = 'sp_changemergearticle')
  3013.         drop procedure sp_changemergearticle
  3014.  
  3015.     if exists (select * from sysobjects
  3016.         where type = 'P'
  3017.             and name = 'sp_MSreinit_hub')
  3018.         drop procedure sp_MSreinit_hub
  3019.  
  3020.     if exists (select * from sysobjects
  3021.         where type = 'P'
  3022.             and name = 'sp_helpmergearticle')
  3023.         drop procedure sp_helpmergearticle
  3024.     
  3025.  
  3026.     if exists (select * from sysobjects
  3027.         where type = 'P'
  3028.             and name = 'sp_dropmergearticle')
  3029.         drop procedure sp_dropmergearticle
  3030.     
  3031.     if exists (select * from sysobjects
  3032.         where type = 'P'
  3033.             and name = 'sp_addmergesubscription')
  3034.         drop procedure sp_addmergesubscription
  3035.     
  3036.     if exists (select * from sysobjects
  3037.         where type = 'P'
  3038.             and name = 'sp_changemergesubscription')
  3039.         drop procedure sp_changemergesubscription
  3040.  
  3041.     if exists (select * from sysobjects
  3042.         where type = 'P'
  3043.             and name = 'sp_helpmergesubscription')
  3044.         drop procedure sp_helpmergesubscription
  3045.  
  3046.     if exists (select * from sysobjects
  3047.         where type = 'P'
  3048.             and name = 'sp_dropmergesubscription')
  3049.         drop procedure sp_dropmergesubscription
  3050.  
  3051.     if exists (select * from sysobjects
  3052.         where type = 'P'
  3053.             and name = 'sp_helpmergefilter')
  3054.         drop procedure sp_helpmergefilter
  3055.  
  3056.     if exists (select * from sysobjects
  3057.         where type = 'P'
  3058.             and name = 'sp_changemergefilter')
  3059.         drop procedure sp_changemergefilter
  3060.     
  3061.     if exists (select * from sysobjects
  3062.         where type = 'P'
  3063.             and name = 'sp_addmergefilter')
  3064.         drop procedure sp_addmergefilter
  3065.     
  3066.     if exists (select * from sysobjects
  3067.         where type = 'P'
  3068.             and name = 'sp_dropmergefilter')
  3069.         drop procedure sp_dropmergefilter
  3070.  
  3071.     if exists (select * from sysobjects
  3072.             where type in ('P ') 
  3073.                 and name = 'sp_MSmergepublishdb')
  3074.         drop procedure sp_MSmergepublishdb
  3075.  
  3076.     if exists (select * from sysobjects
  3077.             where type in ('P ') 
  3078.                 and name = 'sp_helpallowmerge_publication')
  3079.         drop procedure sp_helpallowmerge_publication
  3080.  
  3081.     if exists (select * from sysobjects
  3082.             where type in ('P ') 
  3083.                 and name = 'sp_enumcustomresolvers')
  3084.         drop procedure sp_enumcustomresolvers
  3085.  
  3086.     if exists (select * from sysobjects
  3087.             where type in ('P ') 
  3088.                 and name = 'sp_MSenumpubreferences')
  3089.         drop procedure sp_MSenumpubreferences
  3090.  
  3091.     if exists (select * from sysobjects
  3092.         where type = 'P ' and name = 'sp_MSscript_dri')
  3093.     drop procedure sp_MSscript_dri
  3094.     
  3095.     if exists (select * from sysobjects
  3096.             where type in ('P ') 
  3097.                 and name = 'sp_MSsubsetpublication')
  3098.         drop procedure sp_MSsubsetpublication
  3099.     if exists (select * from sysobjects
  3100.             where type = 'P'
  3101.                 and name = 'sp_generatefilters')
  3102.         drop procedure sp_generatefilters
  3103.     if exists (select * from sysobjects
  3104.             where type = 'P'
  3105.                 and name = 'sp_MSmakejoinfilter')
  3106.         drop procedure sp_MSmakejoinfilter
  3107.     if exists (select * from sysobjects
  3108.             where type = 'P'
  3109.                 and name = 'sp_MSmakeexpandproc')
  3110.         drop procedure sp_MSmakeexpandproc
  3111.     if exists (select * from sysobjects
  3112.             where type = 'P'
  3113.                 and name = 'sp_MSindexcolfrombin')
  3114.         drop procedure sp_MSindexcolfrombin
  3115.  
  3116.     if exists (select * from sysobjects
  3117.             where type = 'P'
  3118.                 and name = 'sp_MShelpvalidationdate')
  3119.         drop procedure sp_MShelpvalidationdate
  3120.  
  3121.     if exists (select * from sysobjects
  3122.                 where type = 'P' and
  3123.                 name = 'sp_helpmergearticleconflicts')
  3124.         drop procedure sp_helpmergearticleconflicts
  3125.  
  3126.     if exists (select * from sysobjects
  3127.                 where type = 'P' and
  3128.                 name = 'sp_MShelpmergeconflictpublications')
  3129.         drop procedure sp_MShelpmergeconflictpublications
  3130.  
  3131.     if exists (select * from sysobjects
  3132.                 where type = 'P' and
  3133.                 name = 'sp_MShelpmergeconflictcounts')
  3134.         drop procedure sp_MShelpmergeconflictcounts
  3135.  
  3136.     if exists (select * from sysobjects
  3137.                 where type = 'P' and
  3138.                 name = 'sp_helpmergeconflictrows')
  3139.         drop procedure sp_helpmergeconflictrows
  3140.  
  3141.     if exists (select * from sysobjects
  3142.                 where type = 'P' and
  3143.                 name = 'sp_helpmergedeleteconflictrows')
  3144.         drop procedure sp_helpmergedeleteconflictrows
  3145.  
  3146.     if exists (select * from sysobjects
  3147.                 where type = 'P' and
  3148.                 name = 'sp_deletemergeconflictrow')
  3149.         drop procedure sp_deletemergeconflictrow
  3150.  
  3151.     if exists (select * from sysobjects
  3152.                 where type = 'P' and
  3153.                 name = 'sp_getmergedeletetype')
  3154.         drop procedure sp_getmergedeletetype
  3155.  
  3156.     if exists (select * from sysobjects
  3157.                 where type = 'P' and
  3158.                 name = 'sp_mergedummyupdate')
  3159.         drop procedure sp_mergedummyupdate
  3160.  
  3161.     if exists (select * from sysobjects
  3162.                 where type = 'P' and
  3163.                 name = 'sp_validatemergepublication')
  3164.         drop procedure sp_validatemergepublication
  3165.  
  3166.     if exists (select * from sysobjects
  3167.                 where type = 'P' and
  3168.                 name = 'sp_validatemergesubscription')
  3169.         drop procedure sp_validatemergesubscription
  3170.  
  3171.     if exists (select * from sysobjects
  3172.                 where type = 'P' and
  3173.                 name = 'sp_addtabletocontents')
  3174.         drop procedure sp_addtabletocontents
  3175.  
  3176.     if exists (select * from sysobjects
  3177.                 where type = 'P' and
  3178.                 name = 'sp_MSaddpubtocontents')
  3179.         drop procedure sp_MSaddpubtocontents
  3180.  
  3181.     if exists (select * from sysobjects
  3182.         where type = 'P' and
  3183.         name = 'sp_MSget_subtypedatasrc')
  3184.         drop procedure sp_MSget_subtypedatasrc
  3185.  
  3186.     if exists (select * from sysobjects
  3187.         where type = 'P'
  3188.             and name = 'sp_addmergealternatepublisher')
  3189.         drop procedure sp_addmergealternatepublisher
  3190.     
  3191.     if exists (select * from sysobjects
  3192.         where type = 'P'
  3193.             and name = 'sp_helpmergealternatepublisher')
  3194.         drop procedure sp_helpmergealternatepublisher
  3195.     
  3196.     if exists (select * from sysobjects
  3197.         where type = 'P'
  3198.             and name = 'sp_dropmergealternatepublisher')
  3199.         drop procedure sp_dropmergealternatepublisher
  3200.     
  3201.  
  3202.     if exists (select * from sysobjects
  3203.         where type = 'P' and 
  3204.         name = 'sp_MScomputemergearticlescreationorder')
  3205.         drop procedure sp_MScomputemergearticlescreationorder
  3206.  
  3207.     if exists (select * from sysobjects
  3208.         where type = 'P' and 
  3209.         name = 'sp_MSclearcolumnbit')
  3210.         drop procedure sp_MSclearcolumnbit
  3211.  
  3212.     if exists (select * from sysobjects
  3213.         where type = 'P' and 
  3214.         name = 'sp_MScomputemergeunresolvedrefs')
  3215.         drop procedure sp_MScomputemergeunresolvedrefs
  3216.  
  3217.     if exists (select * from sysobjects
  3218.         where type = 'P' and 
  3219.         name = 'sp_MSgetpubinfo')
  3220.         drop procedure sp_MSgetpubinfo 
  3221.         
  3222.     if exists (select * from sysobjects
  3223.         where type = 'P' and
  3224.         name = 'sp_MSaddmergedynamicsnapshotjob')
  3225.         drop procedure sp_MSaddmergedynamicsnapshotjob
  3226.  
  3227.     if exists (select * from sysobjects
  3228.         where type = 'P' and
  3229.         name = 'sp_MSpropagateschematorepubs')
  3230.         drop procedure sp_MSpropagateschematorepubs
  3231.     
  3232.     if exists (select * from sysobjects
  3233.         where type = 'P' and
  3234.         name = 'sp_MSdropmergedynamicsnapshotjob')
  3235.         drop procedure sp_MSdropmergedynamicsnapshotjob
  3236.  
  3237.     if exists (select * from sysobjects 
  3238.         where type = 'P' and
  3239.         name = 'sp_MShelpmergedynamicsnapshotjob')
  3240.         drop procedure sp_MShelpmergedynamicsnapshotjob
  3241. go
  3242.  
  3243. exec dbo.sp_MS_marksystemobject sp_MSdrop_rladmin
  3244. go
  3245.  
  3246. EXEC dbo.sp_MSdrop_rladmin
  3247. GO
  3248.  
  3249. raiserror('Creating procedure sp_MSaddmergepub_snapshot', 0,1)
  3250. GO
  3251.  
  3252. CREATE PROCEDURE sp_MSaddmergepub_snapshot (
  3253.     @publication            sysname,    
  3254.     @freqtype               int = 4 ,           /* 4== Daily */
  3255.     @freqinterval           int = 1,            /* Every day */
  3256.     @freqsubtype            int = 4,            /* Sub interval = Minute */
  3257.     @freqsubinterval        int = 5,            /* Every five minutes */
  3258.     @freqrelativeinterval   int = 1, 
  3259.     @freqrecurrencefactor   int = 0, 
  3260.     @activestartdate        int = 0,            /* 12:00 am - 11:59 pm */
  3261.     @activeenddate          int = 99991231 ,    /* No start date */ 
  3262.     @activestarttimeofday   int = 0,        
  3263.     @activeendtimeofday     int = 235959,       /* No end time */               
  3264.     @newtaskid              int = 0 OUTPUT,
  3265.     @snapshot_job_name      nvarchar(100) = null
  3266. ) AS
  3267.  
  3268.     SET NOCOUNT ON
  3269.  
  3270.     /*
  3271.     ** Declarations.
  3272.     */
  3273.     declare @retcode                int
  3274.     declare @distributor            sysname
  3275.     declare @dist_rpcname           sysname
  3276.     declare @distribdb              sysname
  3277.     declare @distproc               nvarchar(300)
  3278.     declare @database               sysname
  3279.     declare @newid                  int
  3280.     declare @fFoundPublication      int
  3281.     declare @task_args              nvarchar(4000)
  3282.     declare @pubid                  uniqueidentifier
  3283.     declare @snapshot_jobid         binary(16)
  3284.     declare @job_existing           bit
  3285.  
  3286.     /*
  3287.     ** Initializations
  3288.     */
  3289.     select @fFoundPublication   = 0 
  3290.     if (@snapshot_job_name is null) or (@snapshot_job_name = N'')
  3291.     begin
  3292.         select @job_existing = 0
  3293.     end
  3294.     else
  3295.     begin
  3296.         select @job_existing = 1
  3297.     end
  3298.  
  3299.     EXEC @retcode = dbo.sp_helpmergepublication @publication, @fFoundPublication output, @pubid output
  3300.  
  3301.     if @@ERROR <> 0 OR @retcode <> 0
  3302.     BEGIN
  3303.         RETURN (1)
  3304.     END
  3305.  
  3306.     /* If the publication does not exist return error */
  3307.     if @fFoundPublication = 0 
  3308.     BEGIN
  3309.         RAISERROR (21040, 11, -1, @publication)
  3310.         RETURN (1)
  3311.     END
  3312.  
  3313.     /* 
  3314.     ** Make sure the publication does not already have a task.
  3315.     */
  3316.     if EXISTS (select * FROM MSmerge_replinfo WHERE repid = @pubid and snapshot_jobid IS NOT NULL)
  3317.     BEGIN
  3318.         RAISERROR (14101, 11, -1, @publication)
  3319.         RETURN(1)
  3320.     END
  3321.  
  3322.     /*
  3323.     ** Get distributor information
  3324.     */
  3325.     EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, 
  3326.         @distribdb = @distribdb OUTPUT,
  3327.         @rpcsrvname = @dist_rpcname OUTPUT 
  3328.         if @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
  3329.         BEGIN
  3330.             RAISERROR (14071, 16, -1)
  3331.             RETURN (1)
  3332.         END
  3333.  
  3334.     select @database = DB_NAME()
  3335.  
  3336.     select @task_args = '-Publisher ' + QUOTENAME(@@SERVERNAME)
  3337.     select @task_args = @task_args + ' -PublisherDB ' + QUOTENAME(@database)
  3338.     select @task_args = @task_args + ' -Distributor ' + QUOTENAME(@distributor)
  3339.     select @task_args = @task_args + ' -Publication ' + QUOTENAME(@publication)
  3340.     select @task_args = @task_args + ' -ReplicationType 2'
  3341.     
  3342.     /* 
  3343.     ** Create task on distributor
  3344.     */
  3345.     SELECT @distproc = RTRIM(@dist_rpcname) + '.' + @distribdb + '.dbo.sp_MSadd_snapshot_agent'
  3346.  
  3347.     EXECUTE @retcode = @distproc 
  3348.         @name = @snapshot_job_name,
  3349.         @publisher = @@SERVERNAME,
  3350.         @publisher_db = @database,
  3351.         @publication = @publication,  
  3352.         @publication_type = 2,          -- Merge type
  3353.         @local_job = 1,  
  3354.         @freqtype = @freqtype, 
  3355.         @freqinterval = @freqinterval, 
  3356.         @freqsubtype = @freqsubtype, 
  3357.         @freqsubinterval = @freqsubinterval, 
  3358.         @freqrelativeinterval = @freqrelativeinterval, 
  3359.         @freqrecurrencefactor = @freqrecurrencefactor, 
  3360.         @activestartdate = @activestartdate,
  3361.         @activeenddate =@activeenddate ,         
  3362.         @activestarttimeofday = @activestarttimeofday,         
  3363.         @activeendtimeofday = @activeendtimeofday,     
  3364.         @command = @task_args, 
  3365.         @snapshot_jobid = @snapshot_jobid OUTPUT,
  3366.         @job_existing = @job_existing 
  3367.  
  3368.    if @@ERROR <> 0 or @retcode <> 0
  3369.         RETURN(1)
  3370.     
  3371.     SELECT @newtaskid = 1
  3372.  
  3373.     UPDATE MSmerge_replinfo set snapshot_jobid = @snapshot_jobid WHERE repid = @pubid
  3374.  
  3375.     if @@ERROR <> 0 
  3376.         RETURN(1)
  3377.             
  3378.     return (0)
  3379. GO
  3380. exec dbo.sp_MS_marksystemobject sp_MSaddmergepub_snapshot
  3381. go
  3382.  
  3383. grant execute on dbo.sp_MSaddmergepub_snapshot to public
  3384. go
  3385.  
  3386.  
  3387. GO
  3388.  
  3389. raiserror('Creating procedure sp_MSdropmergepub_snapshot', 0,1)
  3390. GO
  3391.  
  3392. CREATE PROCEDURE sp_MSdropmergepub_snapshot (
  3393.     @publication sysname,
  3394.     @ignore_distributor bit = 0
  3395. ) AS
  3396.  
  3397.     SET NOCOUNT ON
  3398.  
  3399.     /*
  3400.     ** Declarations.
  3401.     */
  3402.     declare @retcode            int
  3403.     declare @distributor        sysname
  3404.     declare @distproc           nvarchar(300)
  3405.     declare @snapshot_jobid     binary(16)
  3406.     declare @fFoundPublication  int
  3407.     declare @pubid              uniqueidentifier
  3408.     declare @distribdb          sysname
  3409.  
  3410.     /*
  3411.     ** Initializations
  3412.     */
  3413.     select @fFoundPublication = 0
  3414.  
  3415.     /* validate the publication */
  3416.     /* If the publication is  not exist found return error */
  3417.     EXEC @retcode = dbo.sp_helpmergepublication @publication, @fFoundPublication output, @pubid output
  3418.     if @@ERROR <> 0 OR @fFoundPublication = 0 OR @retcode <> 0
  3419.     BEGIN
  3420.         RETURN (1)
  3421.     END
  3422.  
  3423.     /*
  3424.     ** Get taskid. Make sure the snapshot_jobid is not NULL only before using MAX
  3425.     ** Otherwise there will be a warnning.
  3426.     */
  3427.     select @snapshot_jobid = max(snapshot_jobid) FROM MSmerge_replinfo WHERE repid = @pubid
  3428.     
  3429.     if (@snapshot_jobid IS NOT NULL)        
  3430.     begin
  3431.  
  3432.     /*
  3433.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  3434.     */
  3435.     if @ignore_distributor = 0
  3436.         begin
  3437.             /*
  3438.             ** Get distributor information
  3439.             */
  3440.             EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  3441.                 @distribdb = @distribdb OUTPUT
  3442.                 if @@error <> 0 OR @retcode <> 0
  3443.                 BEGIN
  3444.                     RAISERROR (14071, 16, -1)
  3445.                     RETURN (1)
  3446.                 END
  3447.  
  3448.             /*
  3449.             ** Delete sync agent of Publication.
  3450.             */
  3451.             declare @dbname sysname
  3452.             set @dbname = DB_NAME()
  3453.             SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_snapshot_agent'
  3454.             EXECUTE @retcode = @distproc 
  3455.                 @publisher = @@SERVERNAME,
  3456.                 @publisher_db = @dbname,
  3457.                 @publication = @publication
  3458.  
  3459.             IF @@ERROR <> 0 or @retcode <> 0
  3460.                 RETURN(1)
  3461.         end
  3462.  
  3463.  
  3464.         /* Update publication's taskid */
  3465.         UPDATE MSmerge_replinfo set snapshot_jobid = NULL WHERE repid = @pubid
  3466.         IF @@ERROR <> 0
  3467.             BEGIN
  3468.             RAISERROR (20072, 16, -1)
  3469.             RETURN (1)
  3470.             END
  3471.  
  3472.     end
  3473.             
  3474.     return (0)      
  3475. GO 
  3476. exec dbo.sp_MS_marksystemobject sp_MSdropmergepub_snapshot 
  3477. go
  3478.  
  3479. grant execute on dbo.sp_MSdropmergepub_snapshot to public
  3480. go
  3481.  
  3482. raiserror('Creating procedure sp_MScheckatpublisher', 0,1)
  3483. GO
  3484.  
  3485. create procedure sp_MScheckatpublisher
  3486.     @pubid                  uniqueidentifier
  3487.     AS
  3488.     -- this routine will be called by sp_addmergearticle, sp_changemergearticle
  3489.     declare @db_name        sysname
  3490.     
  3491.     select @db_name =db_name from sysmergesubscriptions
  3492.         where (pubid=@pubid) and (subid=@pubid) 
  3493.         IF @db_name <> db_name() 
  3494.             RETURN 1
  3495.         ELSE 
  3496.             RETURN 0
  3497.             
  3498. go
  3499. exec dbo.sp_MS_marksystemobject sp_MScheckatpublisher
  3500. go
  3501.  
  3502. grant execute on dbo.sp_MScheckatpublisher to public
  3503. go
  3504.          
  3505. raiserror('Creating procedure sp_MSaddmergeschemaarticle', 0,1)
  3506. GO
  3507.  
  3508. create procedure sp_MSaddmergeschemaarticle
  3509.     @pubid                              uniqueidentifier,    
  3510.     @article                            sysname,
  3511.     @source_object                      sysname,
  3512.     @type                               tinyint, 
  3513.     @description                        nvarchar(255),
  3514.     @status                             nvarchar(10),   
  3515.     @pre_creation_command               int,
  3516.     @creation_script                    nvarchar(255),
  3517.     @source_owner                       sysname,
  3518.     @destination_owner                  sysname,    
  3519.     @schema_option                      binary(8),
  3520.     @destination_object                 sysname,
  3521.     @qualified_name                     nvarchar(270),
  3522.     @publication                        sysname, 
  3523.     @snapshot_ready                     int,
  3524.     @force_invalidate_snapshot          bit
  3525. AS
  3526.     SET NOCOUNT ON
  3527.  
  3528.     DECLARE @retcode              int
  3529.     DECLARE @objid                int    
  3530.     DECLARE @artid                uniqueidentifier
  3531.     DECLARE @bInTran              bit
  3532.     DECLARE @valid_schema_options int
  3533.     DECLARE @bump_to_80           bit
  3534.         
  3535.     SELECT @bInTran = 0
  3536.     SELECT @objid = OBJECT_ID(@qualified_name)
  3537.     -- We are going to bump the compatibility level anyway
  3538.     -- since we are adding schema only articles
  3539.     SELECT @bump_to_80 = 1
  3540.     RAISERROR(21391, 10, -1, @publication)
  3541.  
  3542.     /*
  3543.     ** Parameter check: Source object type must match
  3544.     ** specified article type.
  3545.     **
  3546.     */
  3547.     -- Type has to be one of 0x20, 0x40, or 0x80 by the time 
  3548.     -- this sp is called
  3549.     IF @type = 0x20
  3550.     BEGIN
  3551.         IF NOT EXISTS (SELECT * 
  3552.                          FROM sysobjects
  3553.                         WHERE id = @objid
  3554.                           AND xtype = 'P ')
  3555.         BEGIN
  3556.             RAISERROR(21219, 16, -1)
  3557.             RETURN (1)
  3558.         END 
  3559.                         
  3560.     END
  3561.     ELSE IF @type = 0x40
  3562.     BEGIN
  3563.         IF NOT EXISTS (SELECT *
  3564.                          FROM sysobjects
  3565.                         WHERE id = @objid
  3566.                           AND xtype = 'V ')
  3567.         BEGIN
  3568.             RAISERROR(21221, 16, -1)
  3569.             RETURN (1)
  3570.         END
  3571.     END
  3572.     ELSE IF @type = 0x80
  3573.     BEGIN
  3574.         IF NOT EXISTS (SELECT *
  3575.                          FROM sysobjects
  3576.                         WHERE id = @objid
  3577.                           AND xtype IN ('FN','TF', 'IF'))
  3578.         BEGIN
  3579.             RAISERROR(21228, 16, -1)
  3580.             RETURN (1)
  3581.         END
  3582.     END
  3583.  
  3584.  
  3585.     /*
  3586.     ** Parameter check: @schema_option
  3587.     ** For proc and func schema only articles, schema_option can 
  3588.     ** only contain the options
  3589.     ** 0x0000000000000001, 0x0000000000002000
  3590.     ** for schema only articles except view. View articles can contain 
  3591.     ** the options 0x0000000000000010, 0x0000000000000020, and 0x0000000000000100 
  3592.     ** in addition to the aforementioned options.
  3593.     */
  3594.     IF @type = 0x40
  3595.     BEGIN
  3596.  
  3597.         -- Since only the lower 32 bits of @schema_option are
  3598.         -- currently used, the following check is sufficient.
  3599.         -- Note that @schema_option should have been padded out already.
  3600.         DECLARE @schema_option_lodword int
  3601.         SELECT @valid_schema_options = 0x2151
  3602.         SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  3603.         IF (@schema_option_lodword & ~@valid_schema_options) <> 0
  3604.         BEGIN
  3605.             RAISERROR (21229, 16, -1)
  3606.             RETURN (1)
  3607.         END
  3608.     END
  3609.     ELSE IF @schema_option NOT IN (0x0000000000000000,
  3610.                                    0x0000000000000001,
  3611.                                    0x0000000000002000,
  3612.                                    0x0000000000002001)
  3613.     BEGIN
  3614.         RAISERROR (21222, 16, -1)
  3615.         RETURN (1)
  3616.     END 
  3617.  
  3618.  
  3619.     /*
  3620.     ** Parameter check: @pre_creation_command must be
  3621.     ** 'drop' (id = 1) or 'none' (id = 0)
  3622.     */
  3623.     IF @pre_creation_command NOT IN (0, 1)
  3624.     BEGIN
  3625.         RAISERROR(21223, 16, -1)
  3626.         RETURN (1)
  3627.     END
  3628.  
  3629.     -- Reuse @artid from articles publishing the same object so we can
  3630.     -- link these articles together during the reinit/republishing scenario 
  3631.  
  3632.     SELECT @artid = NULL
  3633.     SELECT @artid = artid 
  3634.       FROM sysmergeschemaarticles 
  3635.      WHERE objid = @objid
  3636.  
  3637.     IF @artid IS NULL
  3638.     BEGIN
  3639.         SELECT @artid = newid()
  3640.     END
  3641.  
  3642.     BEGIN TRAN
  3643.     SAVE TRANSACTION sp_MSaddmergeschemaarticle
  3644.     SELECT @bInTran = 1
  3645.  
  3646.     IF @snapshot_ready > 0
  3647.     BEGIN
  3648.         IF @force_invalidate_snapshot = 0
  3649.         BEGIN
  3650.             RAISERROR(21364, 16, -1, @article)
  3651.             GOTO FAILURE
  3652.         END
  3653.         RAISERROR(21360, 10, -1, @publication)
  3654.         SELECT @bump_to_80 = 1
  3655.         UPDATE sysmergepublications 
  3656.            SET snapshot_ready=2 
  3657.          WHERE pubid=@pubid
  3658.         IF @@ERROR<>0
  3659.             GOTO FAILURE
  3660.     END
  3661.  
  3662.     INSERT sysmergeschemaarticles (name, type, objid, artid, description,
  3663.         pre_creation_command, pubid, status, creation_script, schema_option,
  3664.         destination_object, destination_owner)
  3665.     VALUES (@article, @type, @objid, @artid, @description, @pre_creation_command,
  3666.         @pubid, 1, @creation_script, @schema_option, @destination_object,
  3667.         @destination_owner)
  3668.  
  3669.     IF @@ERROR <> 0
  3670.         GOTO FAILURE
  3671.  
  3672.     -- Mark the source object as a replication object so
  3673.     -- user cannot drop it 
  3674.     UPDATE sysobjects SET replinfo = replinfo | 0x00000200 WHERE id = @objid   
  3675.     
  3676.     IF @@ERROR <> 0
  3677.         GOTO FAILURE
  3678.  
  3679.     IF @bump_to_80=1
  3680.     BEGIN
  3681.         EXEC @retcode = sp_MSBumpupCompLevel @pubid, 40
  3682.         IF @@ERROR<>0 or @retcode<>0
  3683.             GOTO FAILURE
  3684.     END
  3685.  
  3686.     COMMIT TRANSACTION 
  3687.     
  3688.     RETURN (0)
  3689.  
  3690. FAILURE:
  3691.  
  3692.     IF @bInTran = 1
  3693.     BEGIN
  3694.         ROLLBACK TRANSACTION sp_MSaddmergeschemaarticle
  3695.         COMMIT TRANSACTION
  3696.     END    
  3697.     RETURN (1)
  3698. go
  3699.  
  3700. exec dbo.sp_MS_marksystemobject sp_MSaddmergeschemaarticle
  3701.  
  3702.  
  3703. raiserror('Creating procedure sp_addmergearticle', 0,1)
  3704. GO
  3705.  
  3706. create procedure sp_addmergearticle
  3707.     @publication            sysname,                            /* publication name */
  3708.     @article                sysname,                            /* article name */
  3709.     @source_object          sysname,                            /* source object name */
  3710.     @type                   sysname = 'table',                  /* article type */
  3711.     @description            nvarchar(255)= NULL,                /* article description */
  3712.     @column_tracking        nvarchar(10) = 'false',             /* column level tracking */
  3713.     @status                 nvarchar(10) = 'unsynced',          /* unsynced, active */
  3714.     @pre_creation_cmd       nvarchar(10) = 'drop',              /* 'none', 'drop', 'delete', 'truncate' */
  3715.     @creation_script        nvarchar(255)= NULL,                /* article schema script */
  3716.     @schema_option          varbinary(8)   = NULL,              /* article schema creation options */
  3717.     @subset_filterclause    nvarchar(1000) = '',                /* filter clause */
  3718.     @article_resolver       nvarchar(255)= NULL,                 /* custom resolver for article */
  3719.     @resolver_info          nvarchar(255) = NULL,                /* custom resolver info */
  3720.     @source_owner           sysname = NULL,
  3721.     @destination_owner        sysname = NULL,
  3722.     @vertical_partition        nvarchar(5) = 'FALSE',                /* vertical partitioning or not */
  3723.     @auto_identity_range    nvarchar(5)    = 'FALSE',                /* set it to false for now - change is possible */
  3724.     @pub_identity_range        bigint    = NULL,
  3725.     @identity_range            bigint = NULL,
  3726.     @threshold                int    = NULL,
  3727.     @verify_resolver_signature         int = 0,                    /* 0=do not verify signature, 1=verify that signature is from trusted source, more values may be added later */
  3728.     @destination_object             sysname = @source_object,
  3729.     @allow_interactive_resolver        nvarchar(5) = 'false',        /* whether article allows interactive resolution or not */
  3730.     @fast_multicol_updateproc        nvarchar(5) = 'true',        /* whether update proc should update multiple columns in one update statement or not. if 0, then separate update issued for each column changed. */
  3731.     @check_permissions        int = 0, /* bitmap where 0x00 for nochecks, 0x01 for insert check, 0x2 for update check, 0x4 for delete check */
  3732.     @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  3733.     AS
  3734.  
  3735.     set nocount on
  3736.  
  3737.     /*
  3738.     ** Declarations.
  3739.     */
  3740.     declare @max_range                bigint
  3741.     declare @publisher                sysname
  3742.     declare @publisher_db            sysname
  3743.     declare @already_published        bit
  3744.     declare @identity_so_far        bigint
  3745.     declare @ver_partition            int
  3746.     declare @sp_resolver            sysname
  3747.     declare @num_columns            smallint
  3748.     declare @pubid                  uniqueidentifier                /* Publication id */
  3749.     declare @db                     sysname
  3750.     declare @identity_support        int
  3751.     declare @object                 sysname
  3752.     declare @owner                  sysname
  3753.     declare @retcode                int
  3754.     declare @objid                  int
  3755.     declare @sync_objid             int
  3756.     declare @typeid                 smallint
  3757.     declare @nickname               int
  3758.     declare @merge_pub_object_bit int
  3759.     declare @column_tracking_id     int
  3760.     declare @cmd                    nvarchar(255)
  3761.     declare @statusid               tinyint --1: inactive; 2: active; 5:new_inactive 6:new_active
  3762.     declare @next_seed                bigint
  3763.     declare @precmdid               int
  3764.     declare @resolver_clsid         nvarchar(50)
  3765.     declare @resolver_clsid_old     nvarchar(50)
  3766.     declare @tablenick              int
  3767.     declare @artid                  uniqueidentifier
  3768.     declare @i                        int
  3769.     declare @max_identity            bigint
  3770.     declare @colname                sysname
  3771.     declare @indid                    int
  3772.     declare @pkkey                    sysname
  3773.     declare @distributor            sysname
  3774.     declare @distribdb              sysname
  3775.     declare @distproc               nvarchar(300)
  3776.     declare @dbname                 sysname
  3777.     declare @replinfo               int
  3778.     declare @db_name                sysname
  3779.     declare @subset                 int
  3780.     declare @is_publisher            int
  3781.     declare @row_size               int
  3782.     declare @sp_name                sysname
  3783.     declare @sp_owner                sysname
  3784.     declare @qualified_name         nvarchar(270)
  3785.     declare @snapshot_ready         tinyint
  3786.     declare @sync_mode                tinyint
  3787.     declare @allow_interactive_bit    bit
  3788.     declare @fast_multicol_updateproc_bit bit
  3789.     declare @additive_resolver        sysname
  3790.     declare @average_resolver        sysname
  3791.     declare @mindate_resolver        sysname
  3792.     declare @needs_pickup            bit
  3793.     declare @maxdate_resolver        sysname
  3794.     declare @minimum_resolver        sysname
  3795.     declare @maximum_resolver        sysname
  3796.     declare @mergetxt_resolver        sysname
  3797.     declare @pricolumn_resolver        sysname
  3798.     declare @xtype                    int
  3799.     declare @xprec                    int
  3800.     declare @initial_setting        bit
  3801.     declare @bump_to_80                bit
  3802.     declare @gen                     int
  3803.     declare @replnick                 int
  3804.     declare @genguid                 uniqueidentifier
  3805.     declare @guidnull                 uniqueidentifier
  3806.     declare @dt                     datetime
  3807.     
  3808.     /* make sure current database is enabled for merge replication */
  3809.     exec @retcode=dbo.sp_MSCheckmergereplication
  3810.     if @@ERROR<>0 or @retcode<>0
  3811.         return (1)
  3812.  
  3813.     /*
  3814.     ** Initializations 
  3815.     */
  3816.     set @guidnull = '00000000-0000-0000-0000-000000000000'
  3817.     select @is_publisher = 0
  3818.     select @initial_setting = 0
  3819.     select @needs_pickup = 0
  3820.     select @bump_to_80 = 0
  3821.     select @already_published = 0
  3822.     select @publisher = @@SERVERNAME
  3823.     select @publisher_db = db_name()
  3824.     select @max_identity    = NULL
  3825.     select @next_seed        = NULL
  3826.     select @statusid        = 0
  3827.     select @resolver_clsid  = NULL
  3828.     select @subset          = 1     /* Const: publication type 'subset' */
  3829.     select @merge_pub_object_bit    = 128
  3830.     select @db_name    = db_name()
  3831.     select @sp_resolver         = 'Microsoft SQLServer Stored Procedure Resolver'
  3832.     select @additive_resolver     = 'Microsoft SQL Server Additive Conflict Resolver'
  3833.     select @average_resolver     = 'Microsoft SQL Server Averaging Conflict Resolver'
  3834.     select @minimum_resolver     = 'Microsoft SQL Server Minimum Conflict Resolver'
  3835.     select @maximum_resolver     = 'Microsoft SQL Server Maximum Conflict Resolver'
  3836.     select @mindate_resolver     = 'Microsoft SQL Server DATETIME (Earlier Wins) Conflict Resolver'
  3837.     select @maxdate_resolver     = 'Microsoft SQL Server DATETIME (Later Wins) Conflict Resolver'
  3838.     select @mergetxt_resolver     = 'Microsoft SQL Server Merge Text Columns Conflict Resolver'
  3839.     select @pricolumn_resolver     = 'Microsoft SQL Server Priority Column Resolver'
  3840.  
  3841.     if @source_owner is NULL
  3842.         begin
  3843.             select @source_owner = user_name(uid) from sysobjects where id = object_id(@source_object)
  3844.             if @source_owner is NULL  
  3845.                 begin
  3846.                     raiserror (14027, 11, -1, @source_object)
  3847.                     return (1)
  3848.                 end
  3849.         end
  3850.     select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object)
  3851.  
  3852.     if @subset_filterclause <> '' and @subset_filterclause is not NULL
  3853.     begin
  3854.     /* check the validity of subset_filterclause */
  3855.     exec ('declare @test int select @test=1 from ' + @qualified_name + ' where (1=2) and ' + @subset_filterclause)
  3856.     if @@ERROR<>0
  3857.         begin
  3858.             raiserror(21256, 16, -1, @subset_filterclause, @article)
  3859.             return (1)
  3860.         end
  3861.     end
  3862.     if @destination_owner is NULL
  3863.         select @destination_owner = 'dbo'
  3864.     
  3865.     /*
  3866.     ** Security Check
  3867.     */
  3868.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  3869.     IF @@ERROR <> 0 or @retcode <> 0
  3870.         return (1)
  3871.  
  3872.     /*
  3873.     ** Pad out the specified schema option to the left
  3874.     */
  3875.     select @schema_option = fn_replprepadbinary8(@schema_option)
  3876.  
  3877.     /*
  3878.     ** Parameter Check: @publication.
  3879.     ** The @publication id cannot be NULL and must conform to the rules
  3880.     ** for identifiers.
  3881.     */   
  3882.         
  3883.     if @publication is NULL
  3884.         begin
  3885.             raiserror (14043, 16, -1, '@publication')
  3886.             return (1)
  3887.         end
  3888.  
  3889.     select @pubid = pubid, @snapshot_ready = snapshot_ready, @sync_mode=sync_mode from sysmergepublications 
  3890.         where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  3891.     if @pubid is NULL
  3892.         begin
  3893.             raiserror (20026, 16, -1, @publication)
  3894.             return (1)
  3895.         end
  3896.  
  3897.     if lower(@article)='all'
  3898.         begin
  3899.             raiserror(21401, 16, -1)
  3900.             return (1)
  3901.         end
  3902.  
  3903.     /*
  3904.     ** Parameter Check: @type
  3905.     ** If the article is added as a 'indexed view schema only' article,
  3906.     ** make sure that the source object is a schema-bound view.
  3907.     ** Conversely, a schema-bound view cannot be published as a 
  3908.     ** 'view schema only' article.
  3909.     */
  3910.     select @type = lower(@type collate SQL_Latin1_General_CP1_CS_AS)
  3911.  
  3912.     if @type = N'indexed view schema only' and objectproperty(object_id(@qualified_name), 'IsSchemaBound') <> 1
  3913.     begin
  3914.         raiserror (21277, 11, -1, @qualified_name)        
  3915.         return (1)    
  3916.     end
  3917.     else if @type = N'view schema only' and objectproperty(object_id(@qualified_name), 'IsSchemaBound') = 1
  3918.     begin
  3919.         raiserror (21275, 11, -1, @qualified_name)
  3920.         return (1)
  3921.     end
  3922.  
  3923.     /*
  3924.     ** Only publisher can call sp_addmergearticle
  3925.     */
  3926.     EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  3927.     IF @@ERROR <> 0 or @retcode <>  0
  3928.         BEGIN
  3929.             RAISERROR (20073, 16, -1)
  3930.             RETURN (1)
  3931.         END
  3932.         
  3933.     /*
  3934.     ** Parameter Check: @article.
  3935.     ** Check to see that the @article is local, that it conforms
  3936.     ** to the rules for identifiers, and that it is a table, and not
  3937.     ** a view or another database object.
  3938.     */
  3939.  
  3940.     if @article is NULL
  3941.         begin
  3942.             raiserror (20045, 16, -1)
  3943.             return (1)
  3944.         end
  3945.  
  3946.     exec @retcode = dbo.sp_MSreplcheck_name @article
  3947.     if @@ERROR <> 0 or @retcode <> 0
  3948.         return(1)
  3949.         
  3950.  
  3951.     /*
  3952.     ** Set the precmdid.  The default type is 'drop'.
  3953.     **
  3954.     **      @precmdid   pre_creation_cmd
  3955.     **      =========   ================
  3956.     **            0     none
  3957.     **            1     drop
  3958.     **            2     delete
  3959.     **            3     truncate
  3960.     */
  3961.     IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop', 'delete', 'truncate')
  3962.        BEGIN
  3963.           RAISERROR (14061, 16, -1)
  3964.           RETURN (1)
  3965.        END
  3966.  
  3967.     /*
  3968.     ** Determine the integer value for the pre_creation_cmd.
  3969.     */
  3970.     IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'none'
  3971.        select @precmdid = 0
  3972.     ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  3973.        select @precmdid = 1
  3974.     ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'delete'
  3975.        select @precmdid = 2
  3976.     ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'truncate'
  3977.        select @precmdid = 3
  3978.  
  3979.  
  3980.     /*
  3981.     ** Set the typeid.  The default type is table.  It can 
  3982.     ** be one of following.
  3983.     **
  3984.     **      @typeid     type
  3985.     **      =======     ========
  3986.     **         0xa      table
  3987.     **        0x20      proc schema only
  3988.     **        0x40      view schema only
  3989.     **        0x80      func schema only
  3990.     **        0x40      indexed view schema only (overloaded)
  3991.     */        
  3992.  
  3993.     IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('table', 'proc schema only', 'view schema only', 'func schema only', 'indexed view schema only')
  3994.        BEGIN
  3995.             RAISERROR (20074, 16, -1)
  3996.             RETURN (1)
  3997.        END
  3998.  
  3999.     IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'table'
  4000.     BEGIN
  4001.        SET @typeid = 0x0a
  4002.     END
  4003.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'proc schema only'
  4004.     BEGIN
  4005.        SET @typeid = 0x20 
  4006.     END
  4007.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'view schema only'
  4008.     BEGIN
  4009.        SET @typeid = 0x40
  4010.     END
  4011.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'indexed view schema only'
  4012.     BEGIN
  4013.        SET @typeid = 0x40
  4014.     END
  4015.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'func schema only'
  4016.     BEGIN
  4017.        SET @typeid = 0x80
  4018.     END
  4019.  
  4020.     select @sync_objid = OBJECT_ID(@qualified_name)
  4021.     if @sync_objid is NULL
  4022.         begin
  4023.             raiserror (14027, 11, -1, @qualified_name)
  4024.             return (1)
  4025.         end
  4026.  
  4027.  
  4028.     if @typeid in (0x20,0x40,0x80)
  4029.     begin
  4030.         if exists (select * from syscomments
  4031.                     where id = @sync_objid
  4032.                       and encrypted = 1)
  4033.         begin
  4034.             raiserror(21004, 16, -1, @source_object)
  4035.             return 1
  4036.         end
  4037.     end
  4038.  
  4039.     /*
  4040.     ** Parameter Check:  @article, @publication.
  4041.     ** Check if the article already exists in this publication.
  4042.     */
  4043.  
  4044.     IF EXISTS (SELECT *
  4045.                  FROM sysmergeextendedarticlesview
  4046.                 WHERE pubid = @pubid
  4047.                   AND name = @article)
  4048.         BEGIN
  4049.             raiserror (21292, 16, -1, @source_object)
  4050.             RETURN (1)
  4051.         END
  4052.         
  4053.     /*
  4054.     ** At this point, all common parameter validations 
  4055.     ** for table and schema only articles have been 
  4056.     ** performed, so branch out here to handle schema
  4057.     ** only articles as a special case.
  4058.     */
  4059.     
  4060.     IF @typeid in (0x20, 0x40, 0x80)
  4061.     BEGIN
  4062.     
  4063.         IF @destination_object IS NULL OR @destination_object = N''
  4064.         BEGIN
  4065.             SELECT @destination_object = @source_object
  4066.         END
  4067.     
  4068.         IF @schema_option IS NULL
  4069.         BEGIN
  4070.             SELECT @schema_option = 0x0000000000000001
  4071.         END
  4072.         EXEC @retcode = dbo.sp_MSaddmergeschemaarticle 
  4073.             @pubid = @pubid,
  4074.             @article = @article,
  4075.             @source_object = @source_object,
  4076.             @type = @typeid,
  4077.             @description = @description,
  4078.             @status = @status,
  4079.             @pre_creation_command = @precmdid,
  4080.             @creation_script = @creation_script,
  4081.             @source_owner = @source_owner,
  4082.             @destination_owner = @destination_owner,
  4083.             @schema_option = @schema_option,
  4084.             @destination_object = @destination_object,
  4085.             @qualified_name = @qualified_name,   
  4086.             @publication = @publication,
  4087.             @snapshot_ready = @snapshot_ready,
  4088.             @force_invalidate_snapshot = @force_invalidate_snapshot
  4089.         
  4090.        RETURN (@retcode)
  4091.     END
  4092.  
  4093.     IF @schema_option IS NULL
  4094.     BEGIN
  4095.         SELECT @schema_option = 0x000000000000CFF1
  4096.     END
  4097.  
  4098.     /*
  4099.     ** If scheme option contains collation or extended properties, 
  4100.     ** bump up the compatibility-level
  4101.     */    
  4102.     -- Since only the lower 32 bits of @schema_option are 
  4103.     -- used, the following check is sufficient. Note that @schema_option is
  4104.     -- already padded out to the left at the beginning of this procedure.
  4105.     declare @schema_option_lodword int
  4106.     declare @xprop_schema_option int
  4107.     declare @collation_schema_option int
  4108.     select @xprop_schema_option = 0x00002000
  4109.     select @collation_schema_option = 0x00001000
  4110.     select @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  4111.     if (@schema_option_lodword & @collation_schema_option) <> 0
  4112.     begin    
  4113.         raiserror(21389, 10, -1, @publication)
  4114.         select @bump_to_80 = 1
  4115.     end
  4116.     if (@schema_option_lodword & @xprop_schema_option) <> 0
  4117.     begin   
  4118.         raiserror(21390, 10, -1, @publication)
  4119.         select @bump_to_80 = 1
  4120.     end
  4121.  
  4122.     /*
  4123.     ** Merge table articles does not really support destination object. It has the same value as source
  4124.     */
  4125.     select @destination_object = @source_object
  4126.  
  4127. /*
  4128.     select @row_size=sum(length) from syscolumns where id=OBJECT_ID(@qualified_name)
  4129.     if @row_size>6000 
  4130.         begin
  4131.             RAISERROR (21062, 16, -1, @qualified_name)  
  4132.             -- RETURN (1)
  4133.         end
  4134. */
  4135.     IF LOWER(@vertical_partition collate SQL_Latin1_General_CP1_CS_AS) = 'false'
  4136.         begin
  4137.             select @ver_partition = 0
  4138.         end
  4139.     else
  4140.         begin            
  4141.             select @ver_partition = 1
  4142.         end
  4143.     select @num_columns=count(*) from syscolumns where id = object_id(@qualified_name)
  4144.  
  4145.     if @num_columns > 246 and LOWER(@vertical_partition collate SQL_Latin1_General_CP1_CS_AS) = 'false'
  4146.         begin
  4147.             RAISERROR (20068, 16, -1, @qualified_name, 246)
  4148.             RETURN (1)
  4149.         end
  4150.  
  4151.     /*
  4152.     **  Get the id of the @qualified_name
  4153.     */
  4154.     select @objid = id, @replinfo = replinfo from sysobjects where id = OBJECT_ID(@qualified_name)
  4155.     if @objid is NULL
  4156.         begin
  4157.             raiserror (14027, 11, -1, @qualified_name)
  4158.             return (1)
  4159.         end
  4160.  
  4161.     /*
  4162.     ** If current publication contains a non-sync subscription, all articles to be added in it
  4163.     ** has to contain a rowguidcol.
  4164.     */
  4165.     if exists (select * from sysmergesubscriptions where pubid = @pubid and sync_type = 2)
  4166.         begin
  4167.             if not exists (select * from syscolumns c 
  4168.                 where c.id=@objid and ColumnProperty(c.id, c.name, 'isrowguidcol') = 1)
  4169.                 begin
  4170.                     raiserror(20086 , 16, -1, @publication)
  4171.                     return (1)
  4172.                 end
  4173.         end
  4174.  
  4175.     /*
  4176.     ** If you want to have identity support, @range and threshold can not be NULL
  4177.     */
  4178.     if LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' and (@identity_range is NULL or @threshold is NULL or @pub_identity_range is NULL)
  4179.         begin
  4180.             raiserror(21193, 16, -1)
  4181.             return (1)
  4182.         end
  4183.  
  4184.     if LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'false' and (@identity_range is not NULL or @threshold is not NULL or @pub_identity_range is not NULL)
  4185.         begin
  4186.             raiserror(21282, 16, -1)
  4187.             return (1)
  4188.         end
  4189.  
  4190.     if @threshold<0 OR @threshold>100
  4191.         begin
  4192.             raiserror(21241, 16, -1)
  4193.             return (1)
  4194.         end
  4195.  
  4196.     if LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4197.         begin
  4198.             select @identity_support = 1
  4199.             if OBJECTPROPERTY(@objid, 'tablehasidentity') <> 1
  4200.             begin
  4201.                 raiserror(21194, 16, -1)
  4202.                 return (1)
  4203.             end
  4204.         
  4205.             if @pub_identity_range <= 1 or @identity_range <= 1
  4206.             begin
  4207.                 raiserror(21232, 16 ,-1)
  4208.                 return 1
  4209.             end
  4210.  
  4211.             select @xtype=xtype, @xprec=xprec from syscolumns where id=@objid and columnproperty(id, name, 'IsIdentity')=1
  4212.             select @max_range =
  4213.                     case @xtype when 52 then power((convert(bigint,2)), 8*2-1) - 1 --smallint 
  4214.                         when 48 then power((convert(bigint,2)), 8-1) - 1          --tinyint
  4215.                         when 56 then power((convert(bigint,2)), 8*4-1) - 1          --int
  4216.                         when 127 then power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62)      --bigint
  4217.                          else
  4218.                             power((convert(bigint,2)), 62) -1 + power((convert(bigint,2)), 62)  -- defaulted to bigint
  4219.                     end
  4220.  
  4221.             if (@xtype=108 or @xtype=106) and @xprec<18
  4222.                 select @max_range = power((convert(bigint,10)), (@xprec+1)) - 1
  4223.         
  4224.             if @pub_identity_range * 2 + @identity_range > (@max_range - IDENT_CURRENT(@source_object))
  4225.                 begin
  4226.                     raiserror(21290, 16, -1)
  4227.                     return (1)
  4228.                 end
  4229.         end
  4230.     else
  4231.         select @identity_support = 0            
  4232.  
  4233.  
  4234.     /*
  4235.     ** Make sure that the table name specified is a table and not a view.
  4236.     */
  4237.  
  4238.     if NOT exists (select * from sysobjects
  4239.         where id = (select OBJECT_ID(@qualified_name)) AND type = 'U')
  4240.         begin
  4241.             raiserror (20074, 16, -1)
  4242.             return (1)
  4243.         end
  4244.  
  4245.     /*
  4246.     ** If the table contains one more columns of type bigint or sql_variant, 
  4247.     ** and the publication is not of type native mode, we bump up the backward 
  4248.     ** compatibility level.
  4249.     */
  4250.     if @sync_mode=0 and EXISTS (SELECT * FROM syscolumns c WHERE c.id = @sync_objid
  4251.                 AND (type_name(c.xtype) = 'bigint' or type_name(c.xtype) = 'sql_variant'))
  4252.     begin
  4253.         raiserror(21357, 10, -1, @publication)
  4254.         select    @bump_to_80 = 1
  4255.     end
  4256.  
  4257.     /*
  4258.     ** 7.0 subscribers do not like data type 'timestamp'
  4259.     */
  4260.     if EXISTS (select * from syscolumns where id=@sync_objid and type_name(xtype) ='timestamp')
  4261.     begin
  4262.         raiserror(21358, 10, -1, @publication)
  4263.         select @bump_to_80 = 1
  4264.     end
  4265.         
  4266.     /*
  4267.     ** Validate the column tracking
  4268.     */
  4269.     if @column_tracking IS NULL OR LOWER(@column_tracking collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  4270.         BEGIN
  4271.             RAISERROR (14148, 16, -1, '@column_tracking')
  4272.             RETURN (1)
  4273.         END
  4274.     if LOWER(@column_tracking collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  4275.         SET @column_tracking_id = 1
  4276.     else 
  4277.         SET @column_tracking_id = 0
  4278.  
  4279.     if @column_tracking_id=0 and @sync_mode = 1 and @ver_partition = 1
  4280.         begin
  4281.             RAISERROR (21244, 16, -1)
  4282.             RETURN (1)
  4283.         end
  4284.  
  4285.        /*
  4286.     ** Parameter Check: @allow_interactive_resolver  
  4287.     */
  4288.     if LOWER(@allow_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  4289.         BEGIN
  4290.             RAISERROR (14148, 16, -1, '@allow_interactive_resolver')
  4291.             RETURN (1)
  4292.         END
  4293.     if LOWER(@allow_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4294.         set @allow_interactive_bit = 1
  4295.     else 
  4296.         set @allow_interactive_bit = 0
  4297.  
  4298.     /*
  4299.     ** Parameter Check: @fast_multicol_updateproc  
  4300.     */
  4301.     if LOWER(@fast_multicol_updateproc collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  4302.         BEGIN
  4303.             RAISERROR (14148, 16, -1, '@fast_multicol_updateproc')
  4304.             RETURN (1)
  4305.         END
  4306.     if LOWER(@fast_multicol_updateproc collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4307.         set @fast_multicol_updateproc_bit = 1
  4308.     else 
  4309.         set @fast_multicol_updateproc_bit = 0
  4310.  
  4311.     /*
  4312.     ** Get the pubid.
  4313.     */
  4314.     SELECT @pubid = pubid FROM sysmergepublications 
  4315.         WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  4316.     if @pubid is NULL
  4317.         begin
  4318.             raiserror (20026, 11, -1, @publication)
  4319.             return (1)
  4320.         end
  4321.  
  4322.     execute @retcode = dbo.sp_MSgetreplnick @pubid = @pubid, @nickname = @nickname output
  4323.     if (@@error <> 0) or @retcode <> 0 or @nickname IS NULL 
  4324.         begin
  4325.         RAISERROR (14055, 11, -1)
  4326.         RETURN(1)
  4327.         end                 
  4328.  
  4329.     /*
  4330.     ** Get distribution server information for remote RPC call.
  4331.     */
  4332.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  4333.                        @distribdb   = @distribdb OUTPUT
  4334.     IF @@ERROR <> 0 or @retcode <> 0 or @distributor is NULL
  4335.     BEGIN
  4336.         RAISERROR (21337, 16, -1)
  4337.         RETURN (1)
  4338.     END
  4339.  
  4340.     /*
  4341.     ** Validate the article resolver
  4342.     */
  4343.     if @article_resolver IS NOT NULL
  4344.         begin
  4345.             if @article_resolver = 'default' OR @article_resolver = ''
  4346.                 begin
  4347.                     select @article_resolver = NULL
  4348.                     select @resolver_clsid = NULL
  4349.                 end                 
  4350.             else
  4351.                 begin
  4352.                     /*
  4353.                     ** Get the distributor info
  4354.                     */
  4355.                     select @distproc = RTRIM(@distributor) + '.master.dbo.xp_regread'
  4356.                     EXECUTE @retcode = @distproc 'HKEY_LOCAL_MACHINE',
  4357.                                   'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver',
  4358.                                   @article_resolver,
  4359.                                   @param = @resolver_clsid  OUTPUT
  4360.  
  4361.                     IF @retcode <> 0 or @resolver_clsid IS NULL
  4362.                         BEGIN
  4363.                           RAISERROR (20020, 16, -1)
  4364.                           RETURN (1)
  4365.                         END
  4366.                 end
  4367.         end
  4368.  
  4369.     /*
  4370.     ** If article resolver is 'SP resolver', make sure that resolver_info refers to an SP or XP;
  4371.     ** Also make sure it is stored with owner qualification
  4372.     */
  4373.     if  @article_resolver = @sp_resolver
  4374.         begin
  4375.             if not exists (select * from sysobjects where id = object_id(@resolver_info) and ( type = 'P' or type = 'X'))
  4376.                 begin
  4377.                     raiserror(21343, 16, -1, @resolver_info)
  4378.                     return (1)
  4379.                 end
  4380.                 
  4381.             select @sp_name = name, @sp_owner=user_name(uid) from sysobjects where id = object_id(@resolver_info)
  4382.             select @resolver_info = QUOTENAME(@sp_owner) + '.' + QUOTENAME(@sp_name) 
  4383.         end
  4384.  
  4385.     /* The following resolvers expect the @resolver_info to be NON NULL */
  4386.     if  @article_resolver = @sp_resolver or 
  4387.         @article_resolver = @additive_resolver or
  4388.         @article_resolver = @average_resolver or
  4389.         @article_resolver = @minimum_resolver or
  4390.         @article_resolver = @maximum_resolver or
  4391.         @article_resolver = @mindate_resolver or
  4392.         @article_resolver = @maxdate_resolver or
  4393.         @article_resolver = @mergetxt_resolver or
  4394.         @article_resolver = @pricolumn_resolver
  4395.         begin
  4396.             if @resolver_info IS NULL 
  4397.                 begin
  4398.                     RAISERROR (21301, 16, -1, @article_resolver)
  4399.                     return (1)
  4400.                 end
  4401.         end
  4402.     /*
  4403.     ** If article resolver uses column names, make sure that resolver_info refers to a valid column.
  4404.     */
  4405.     if  @article_resolver = @pricolumn_resolver or
  4406.         @article_resolver = @additive_resolver or
  4407.         @article_resolver = @average_resolver or
  4408.         @article_resolver = @minimum_resolver or
  4409.         @article_resolver = @maximum_resolver
  4410.         begin
  4411.             if not exists (select * from syscolumns where id = @objid and name=@resolver_info)
  4412.                 begin
  4413.                     RAISERROR (21501, 16, -1, @article_resolver)
  4414.                     return (1)
  4415.                 end
  4416.         end
  4417.     /*
  4418.     ** If article resolver is 'mindate/maxdate resolver', make sure that resolver_info refers to a column that is of datatype 'datetime' or smalldatetime
  4419.     */
  4420.     if  @article_resolver = @mindate_resolver or
  4421.         @article_resolver = @maxdate_resolver
  4422.         begin
  4423.             if not exists (select * from syscolumns where id = @objid and name=@resolver_info and type_name(xtype)='datetime' or type_name(xtype) = 'smalldatetime' )
  4424.                 begin
  4425.                     RAISERROR (21302, 16, -1, @article_resolver)
  4426.                     return (1)
  4427.                 end
  4428.         end
  4429.  
  4430.     /* The following resolvers expect the article to be column tracked - warn that the default resolver will be used */
  4431.     if  @article_resolver = @additive_resolver or
  4432.         @article_resolver = @average_resolver or
  4433.         @article_resolver = @mergetxt_resolver
  4434.         begin
  4435.             if @column_tracking_id = 0
  4436.                 begin
  4437.                     RAISERROR (21303, 10, -1, @article, @article_resolver)
  4438.                 end
  4439.                 
  4440.         end
  4441.  
  4442.     if @resolver_info IS NOT NULL and @article_resolver IS NULL
  4443.         begin
  4444.             RAISERROR (21300, 10, -1, @article)
  4445.             set @resolver_info = NULL
  4446.         end
  4447.  
  4448.     /* Make sure that coltracking option matches */
  4449.     if exists (select * from sysmergearticles where objid = @objid and
  4450.             identity_support <> @identity_support)
  4451.         begin
  4452.             raiserror (21240, 16, -1, @source_object)
  4453.             return (1)
  4454.         end
  4455.  
  4456.     -- Do not allow the table to be published by both merge and queued tran
  4457.     if exists (select * from sysobjects where name = 'syspublications')
  4458.     begin
  4459.         if exists (select * from syspublications p, sysarticles a where 
  4460.             p.allow_queued_tran = 1 and
  4461.             p.pubid = a.pubid and
  4462.             a.objid = @objid)
  4463.         begin
  4464.             declare @obj_name sysname
  4465.             select @obj_name = object_name(@objid)
  4466.             raiserror(21266, 16, -1, @obj_name)
  4467.             return (1)
  4468.         end
  4469.     end
  4470.  
  4471.     if exists (select * from sysmergearticles where objid=@objid and pubid in(select pubid from sysmergepublications where UPPER(publisher)=UPPER(@publisher) 
  4472.                 and publisher_db=@publisher_db))
  4473.     select @already_published = 1
  4474.  
  4475.     if @already_published = 1 and LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4476.     begin
  4477.         raiserror(21359, 10, -1, @publication)
  4478.         select @bump_to_80 = 1
  4479.         if exists (select * from MSrepl_identity_range where objid=@objid and 
  4480.             ((pub_range<>@pub_identity_range) or (range <> @identity_range) or (threshold <> @threshold)))
  4481.             begin
  4482.                 raiserror(21291, 16, -1)
  4483.                 return (1)
  4484.             end
  4485.     end
  4486.     
  4487.     /*
  4488.     **  Add article to sysmergearticles and update sysobjects category bit.
  4489.     */
  4490.     begin tran
  4491.     save TRAN sp_addmergearticle
  4492.  
  4493.     /*
  4494.     ** We used to prevent an article from being added to a publication whose snapshot
  4495.     ** has been run already. Now we change this so that it is acceptable by doing reinit.
  4496.     */
  4497.         if @snapshot_ready > 0 
  4498.         begin
  4499.             if @force_invalidate_snapshot = 0
  4500.             begin
  4501.                 raiserror(21364, 16, -1, @article)
  4502.                 goto FAILURE
  4503.             end
  4504.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  4505.             if @@ERROR<>0
  4506.                 goto FAILURE
  4507.         end
  4508.  
  4509.     /* 
  4510.     ** article status 5 or 6 means there is at least one new article after snapshot is ready
  4511.     ** hence all articles added after that point will be new articles as well, regardless of snapshot_ready value.
  4512.     */
  4513.         if @snapshot_ready>0 or exists (select * from sysmergearticles where pubid=@pubid and (status=5 or status=6))
  4514.         begin
  4515.             select @needs_pickup=1
  4516.         end
  4517.  
  4518.  
  4519.         /*
  4520.         ** the case when @already_publisher=1 has been handled outside of the transaction
  4521.         */
  4522.         if LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' and @already_published = 0
  4523.         begin
  4524.             -- Set the range to negtive if incr of the identity is negtive
  4525.             if IDENT_INCR(@source_object) < 0
  4526.             begin
  4527.                 select @pub_identity_range = -1 * @pub_identity_range;
  4528.                 select @identity_range = -1 * @identity_range;
  4529.             end
  4530.             raiserror(21359, 10, -1, @publication)
  4531.             select @bump_to_80 = 1
  4532.             select @next_seed = next_seed, @max_identity=max_identity from MSrepl_identity_range where objid=@objid
  4533.             select @identity_so_far = 0
  4534.             if @next_seed is NULL
  4535.             begin
  4536.                 select @initial_setting = 1 -- adjust for existing rows, only for original publisher
  4537.                 select @is_publisher= 1 --original publisher
  4538.                 select @identity_so_far = IDENT_CURRENT(@source_object)
  4539.                 if @identity_so_far is NULL
  4540.                     begin
  4541.                         select @next_seed = IDENT_SEED(@source_object)
  4542.                         select @identity_so_far = @next_seed
  4543.                     end
  4544.                 else
  4545.                     select @next_seed = @identity_so_far
  4546.  
  4547.                 -- use boundary values by cutting off odds,    
  4548.                 -- and always give publisher side one more range to allow for existing rows.                
  4549.  
  4550.                 /* To avoid div by zero errors, error out if pub_range is 0 */
  4551.                 if @pub_identity_range = 0
  4552.                     begin
  4553.                         goto FAILURE
  4554.                     end
  4555.                 select @next_seed = (@next_seed/@pub_identity_range) * @pub_identity_range 
  4556.  
  4557.                 -- to compensate publisher side an extra range in case it loses some slots by rounding up.
  4558.                 -- which only happens when the identity incremental is a positive value
  4559.  
  4560.                 if (((@pub_identity_range > 0) and (@identity_so_far > @next_seed))
  4561.                     OR
  4562.                     ((@pub_identity_range < 0) and (@identity_so_far < @next_seed))) --to make it symmetric both directions
  4563.                     
  4564.                     select @next_seed = @next_seed + @pub_identity_range
  4565.                     
  4566.                 select @max_identity = @max_range --max range decided by data type of identity column
  4567.                 
  4568.                 insert MSrepl_identity_range(objid, next_seed, pub_range, range, max_identity, threshold, current_max)
  4569.                     values (@objid,@next_seed + @pub_identity_range, @pub_identity_range, @identity_range, @max_identity, @threshold, @next_seed + @pub_identity_range)
  4570.             end    
  4571.             else
  4572.             begin
  4573.                 select @is_publisher=2 -- republisher
  4574.                 update MSrepl_identity_range set current_max = @next_seed + @pub_identity_range,
  4575.                                                  pub_range = @pub_identity_range,
  4576.                                                  threshold= @threshold,
  4577.                                                  range = @identity_range
  4578.                     where objid=@objid
  4579.                 if @@ERROR<>0
  4580.                     goto FAILURE
  4581.             end
  4582.                 
  4583.             select @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSinsert_identity'
  4584.             SELECT @dbname =  DB_NAME()
  4585.             exec @retcode = @distproc @publisher = @publisher,
  4586.                                       @publisher_db = @publisher_db,
  4587.                                       @identity_support=@identity_support,
  4588.                                       @tablename=@source_object,
  4589.                                       @pub_identity_range = @pub_identity_range,
  4590.                                       @identity_range =@identity_range,
  4591.                                       @threshold =@threshold,
  4592.                                       @next_seed = @next_seed,
  4593.                                       @max_identity=@max_identity
  4594.             if @retcode<>0 or @@ERROR<>0
  4595.                 goto FAILURE
  4596.                 
  4597.             /* This is to change identity column to 'not for replication' if not having been so already */
  4598.             select @colname=NULL
  4599.             select @colname = name from syscolumns  where
  4600.                  id = @objid and
  4601.                  colstat & 0x0001 <> 0 and -- is identity
  4602.                  colstat & 0x0008 = 0 -- No 'not for repl' property
  4603.             if @colname is not null
  4604.             begin
  4605.                 exec @retcode  = dbo.sp_replupdateschema @source_object
  4606.                 -- Mark 'not for repl'
  4607.                 update syscolumns set colstat = colstat | 0x0008 where
  4608.                     id = @objid and name = @colname
  4609.                 -- Single to refresh the object cache.
  4610.                 exec @retcode  = dbo.sp_replupdateschema @source_object
  4611.                 IF @@ERROR <> 0 OR @retcode <> 0
  4612.                     goto FAILURE
  4613.             end
  4614.  
  4615.         end
  4616.  
  4617.         select @artid = artid from sysmergearticles where objid = @objid
  4618.         select @statusid = 1  /*default status is inactive */
  4619.  
  4620.         if @artid is NULL
  4621.             begin
  4622.                 set @artid = newid()
  4623.                 if @@ERROR <> 0
  4624.                     goto FAILURE
  4625.                 execute @retcode = dbo.sp_MSgentablenickname @tablenick output, @nickname, @objid
  4626.                 if @@ERROR <> 0 OR @retcode <> 0
  4627.                     goto FAILURE
  4628.             end
  4629.         /* Clone the article properties if article has already been published (in a different pub) */
  4630.         else
  4631.             begin
  4632.             /*
  4633.             ** Parameter Check:  @article, @publication.
  4634.             ** Check if the table already exists in this publication.
  4635.             */
  4636.             if exists (select * from sysmergearticles
  4637.                 where pubid = @pubid AND artid = @artid)
  4638.                 begin
  4639.                     raiserror (21292, 16, -1, @source_object)
  4640.                     goto FAILURE
  4641.                 end
  4642.             
  4643.             /* Make sure that coltracking option matches */
  4644.             if exists (select * from sysmergearticles where artid = @artid and
  4645.                          column_tracking <> @column_tracking_id)
  4646.                 begin
  4647.                     raiserror (20030, 16, -1, @article)
  4648.                     goto FAILURE
  4649.                 end
  4650.  
  4651.             /* Reuse the article nickname if article has already been published (in a different pub)*/
  4652.             select @tablenick = nickname from sysmergearticles where artid = @artid
  4653.             if @tablenick IS NULL
  4654.                 goto FAILURE
  4655.                 
  4656.             /* Make sure that @resolver_clsid matches the existing resolver_clsid */
  4657.             select @resolver_clsid_old = resolver_clsid from sysmergearticles where artid = @artid 
  4658.             if ((@resolver_clsid IS NULL AND @resolver_clsid_old IS NOT NULL) OR
  4659.                 (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NULL) OR
  4660.                 (@resolver_clsid IS NOT NULL AND @resolver_clsid_old IS NOT NULL AND @resolver_clsid_old <> @resolver_clsid))
  4661.                 begin
  4662.                     raiserror (20037, 16, -1, @article)
  4663.                     goto FAILURE
  4664.                 end
  4665.  
  4666.             /* Insert to articles, copying some stuff from other article row */
  4667.             insert into sysmergearticles (name, type, objid, sync_objid, artid, description,
  4668.                     pre_creation_command, pubid, nickname, column_tracking, status,
  4669.                     creation_script, article_resolver,
  4670.                     resolver_clsid, schema_option, 
  4671.                     destination_object, destination_owner, subset_filterclause, view_type, resolver_info, gen_cur, 
  4672.                     missing_cols, missing_col_count, excluded_cols, excluded_col_count, identity_support,
  4673.                     before_image_objid, before_view_objid, verify_resolver_signature, allow_interactive_resolver, 
  4674.                     fast_multicol_updateproc, check_permissions)
  4675.                 -- use top 1, distinct could return more than one matching row if status different on partitioned articles
  4676.                 select top 1 @article, type, objid, @sync_objid, @artid, @description, @precmdid,
  4677.                     @pubid, nickname, column_tracking, @statusid, @creation_script,
  4678.                     article_resolver, resolver_clsid, @schema_option, @destination_object, @destination_owner, @subset_filterclause, 
  4679.                     0, resolver_info, gen_cur, 0x00, 0, 0x00,0, identity_support,
  4680.                     before_image_objid, before_view_objid, verify_resolver_signature, allow_interactive_resolver, 
  4681.                     fast_multicol_updateproc, check_permissions
  4682.                     from sysmergearticles where artid = @artid
  4683.  
  4684.             /* Jump to end of transaction  */
  4685.             goto DONE_TRAN
  4686.             end
  4687.  
  4688.         /* Add the specific GUID based replication columns to sysmergearticles */
  4689.         insert sysmergearticles (name, objid, sync_objid, artid, type, description, pubid, nickname, 
  4690.                 column_tracking, status, schema_option, pre_creation_command, destination_object, destination_owner, 
  4691.                 article_resolver, resolver_clsid, subset_filterclause, view_type, resolver_info, columns,
  4692.                 missing_cols, missing_col_count, excluded_cols, excluded_col_count, identity_support,
  4693.                 before_image_objid, before_view_objid, verify_resolver_signature, creation_script, allow_interactive_resolver, 
  4694.                 fast_multicol_updateproc, check_permissions)
  4695.         values (@article, @objid, @sync_objid, @artid, @typeid, @description, @pubid, @tablenick, 
  4696.                 @column_tracking_id, @statusid, @schema_option, @precmdid, @destination_object, @destination_owner, 
  4697.                 @article_resolver, @resolver_clsid, @subset_filterclause, 0, @resolver_info, NULL,
  4698.                  0x00, 0, 0x00,0, @identity_support, NULL, NULL, @verify_resolver_signature, @creation_script, @allow_interactive_bit, 
  4699.                  @fast_multicol_updateproc_bit, @check_permissions)
  4700.         if @@ERROR <> 0
  4701.             goto FAILURE
  4702.  
  4703.         exec @retcode = dbo.sp_replupdateschema @qualified_name
  4704.         if @@ERROR <> 0 or @retcode <> 0
  4705.             goto FAILURE
  4706.         update sysobjects set replinfo = (replinfo | @merge_pub_object_bit) where id = @objid
  4707.         if @@ERROR <> 0
  4708.             goto FAILURE
  4709.  
  4710.         /* set up the article's gen-cur */
  4711.         set @genguid = newid()
  4712.         set @dt = getdate()
  4713.  
  4714.         exec @retcode=sp_MSgetreplnick @nickname = @replnick out
  4715.         if @retcode<>0 or @@error<>0 
  4716.             goto FAILURE
  4717.  
  4718.         /*
  4719.         ** If there are no zero generation tombstones or rows, add a dummy row in there. 
  4720.         */
  4721.            if not exists (select * from MSmerge_genhistory)
  4722.             begin
  4723.             begin tran
  4724.                insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) values
  4725.                 (@genguid, @genguid, 1, 0, @replnick, @dt)
  4726.             if (@@error <> 0)
  4727.                 begin
  4728.                 goto FAILURE
  4729.                 end    
  4730.             commit tran
  4731.             end
  4732.  
  4733.         /* Make a generation and update the article's gen_cur */
  4734.         select @gen = max(gen_cur) from sysmergearticles (updlock holdlock) where nickname = @tablenick and gen_cur is not null
  4735.         if @gen is null
  4736.             begin
  4737.             set @genguid = newid()
  4738.             set @dt = getdate()
  4739.             insert into MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) 
  4740.                 select @genguid, @guidnull, COALESCE(1 + max(generation), 1), @tablenick, @replnick, @dt from MSmerge_genhistory (updlock)
  4741.             if (@@error <> 0)
  4742.                 goto FAILURE
  4743.             select @gen =  generation from MSmerge_genhistory where guidsrc = @genguid
  4744.             update sysmergearticles set gen_cur = @gen where nickname = @tablenick
  4745.             if (@@error <> 0)
  4746.                 goto FAILURE
  4747.             end
  4748.  
  4749.         /* If the article status is active then prepare the article for merge replication */
  4750.         if @status = 'active'
  4751.             begin
  4752.                 /* Get a holdlock on the underlying table */
  4753.                 select @cmd = 'select * into #tab1 from '
  4754.                 select @cmd = @cmd + @qualified_name 
  4755.                 select @cmd = @cmd + '(TABLOCK HOLDLOCK) where 1 = 2 '
  4756.                 execute(@cmd)
  4757.  
  4758.                 /* Add the guid column to the user table */
  4759.                 execute @retcode = dbo.sp_MSaddguidcolumn @source_owner, @source_object
  4760.                 if @@ERROR <> 0 OR  @retcode <> 0  -- NOTE: new change
  4761.                     goto FAILURE
  4762.  
  4763.                 /* Create an index on the rowguid column in the user table */
  4764.                 execute @retcode = dbo.sp_MSaddguidindex @publication, @source_owner, @source_object
  4765.                 if @@ERROR <> 0 OR @retcode <> 0
  4766.                     goto FAILURE
  4767.  
  4768.                 /* Create the merge triggers on the base table */
  4769.                 execute @retcode = dbo.sp_MSaddmergetriggers @qualified_name, NULL, @column_tracking_id
  4770.                 if @@ERROR <> 0 OR @retcode <> 0
  4771.                     goto FAILURE 
  4772.  
  4773.                 /* Create the merge insert/update stored procedures for the base table */
  4774.                 execute @retcode = dbo.sp_MSsetartprocs @publication, @article
  4775.                 if @@ERROR <> 0 OR @retcode <> 0
  4776.                     goto FAILURE
  4777.  
  4778.                 /* Set the article status to be active so that Snapshot does not do this again */
  4779.                 select @statusid = 2 /* Active article */
  4780.                 update sysmergearticles set status = @statusid where artid = @artid
  4781.                 if @@ERROR <> 0 
  4782.                     goto FAILURE
  4783.             end
  4784.         
  4785. DONE_TRAN:                
  4786.             /* identity range control is row level. So one the one is needed for each table */
  4787.             if @identity_support=1 and @already_published=0
  4788.             begin
  4789.  
  4790.                 exec @retcode = sp_MSreseed @objid=@objid,
  4791.                                         @next_seed=@next_seed,
  4792.                                         @range = @pub_identity_range,
  4793.                                         @is_publisher=@is_publisher,
  4794.                                         @check_only = 1,
  4795.                                         @initial_setting = @initial_setting,
  4796.                                         @bound_value = @identity_so_far
  4797.                 if @@ERROR<>0 or @retcode<>0
  4798.                         goto FAILURE
  4799.             end
  4800.  
  4801.     /*
  4802.     ** Set all bits to '1' in the columns column to include all columns.
  4803.     */
  4804.  
  4805.         IF @ver_partition = 0 --meanning no vertical partition needed.
  4806.         BEGIN
  4807.             EXECUTE @retcode  = dbo.sp_mergearticlecolumn @publication=@publication, @article=@article, @schema_replication='true'            
  4808.             IF @@ERROR <> 0 OR @retcode <> 0
  4809.             BEGIN
  4810.                 RAISERROR(21198, 16, -1)
  4811.                 goto FAILURE
  4812.             END
  4813.         END
  4814.  
  4815.         /*
  4816.         **  Set all bits to '1' for all columns in the primary key.
  4817.         */
  4818.         ELSE
  4819.         BEGIN
  4820.             SELECT @indid = indid FROM sysindexes WHERE id = @objid AND (status & 2048) <> 0    /* PK index */
  4821.             /*
  4822.             **  First we'll figure out what the keys are.
  4823.             */
  4824.             SELECT @i = 1
  4825.             WHILE (@i <= 16)
  4826.             BEGIN
  4827.                 SELECT @pkkey = INDEX_COL(@source_object, @indid, @i)
  4828.                 if @pkkey is NULL
  4829.                     break
  4830.                 EXECUTE @retcode  = dbo.sp_mergearticlecolumn @publication, @article, @pkkey, 'add'
  4831.                 IF @@ERROR <> 0 OR @retcode <> 0
  4832.                 BEGIN
  4833.                     RAISERROR(21198, 16, -1)
  4834.                     goto FAILURE
  4835.                 END
  4836.                 select @i = @i + 1
  4837.             END
  4838.             /*
  4839.             ** make sure any existing rowguidcol is in the partition. We can not live without it.
  4840.             */
  4841.             select @colname=NULL
  4842.             select @colname = name from syscolumns where id = @objid 
  4843.                 and ColumnProperty(@objid, name, 'isrowguidcol') = 1
  4844.             if @colname is not NULL
  4845.             BEGIN
  4846.                 EXECUTE @retcode  = dbo.sp_mergearticlecolumn @publication, @article, @colname, 'add'
  4847.                 if @@error<>0 or @retcode<>0
  4848.                     goto FAILURE
  4849.             END
  4850.         END
  4851.  
  4852.         exec @retcode = sp_MSfillupmissingcols @publication, @source_object
  4853.         if @retcode<>0 or @@ERROR<>0
  4854.             goto FAILURE
  4855.  
  4856.         /*
  4857.         ** For articles with subset filter clause - set the pub type to subset
  4858.         */
  4859.         if len(@subset_filterclause) > 0
  4860.             begin
  4861.                 execute @retcode = dbo.sp_MSsubsetpublication @publication
  4862.                 if @@ERROR <> 0 or @retcode<>0
  4863.                     goto FAILURE
  4864.             end                     
  4865.  
  4866.         SELECT @dbname =  DB_NAME()
  4867.         
  4868.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  4869.             '.dbo.sp_MSadd_article'
  4870.         EXECUTE @retcode = @distproc
  4871.             @publisher = @@SERVERNAME,
  4872.             @publisher_db = @dbname,
  4873.             @publication = @publication,
  4874.             @article = @article,
  4875.             @destination_object = @destination_object,
  4876.             @source_owner = @source_owner,
  4877.             @source_object = @source_object,
  4878.             @description = @description
  4879.             -- @article_id = NULL
  4880.         IF @@ERROR <> 0 or @retcode <> 0
  4881.             BEGIN
  4882.                 goto FAILURE
  4883.             END
  4884.  
  4885.         if @bump_to_80=1
  4886.             begin
  4887.                 exec @retcode = sp_MSBumpupCompLevel @pubid, 40
  4888.                 if @@ERROR<>0 or @retcode<>0
  4889.                     goto FAILURE
  4890.             end
  4891.         if @needs_pickup=1
  4892.             begin
  4893.                 declare @needs_pick_value int 
  4894.                 select @needs_pick_value=5 --new_inactive status
  4895.                 update sysmergearticles set status=@needs_pick_value where artid = @artid and pubid=@pubid
  4896.                 if @@ERROR<>0
  4897.                     goto FAILURE
  4898.  
  4899.                 /* 
  4900.                 ** Add the guid column to the user table if needed, cause snapshot_ready>0 would imply
  4901.                 ** this article has got a rowguid column. No need to add index, triggers, or procedures
  4902.                 ** as snapshot run will take care of those.
  4903.                 */
  4904.                 execute @retcode = dbo.sp_MSaddguidcolumn @source_owner, @source_object
  4905.                 if @@ERROR <> 0 OR  @retcode <> 0  -- NOTE: new change
  4906.                     goto FAILURE
  4907.  
  4908.                 execute @retcode = dbo.sp_MSaddguidindex @publication, @source_owner, @source_object
  4909.                 if @@ERROR <> 0 OR @retcode <> 0
  4910.                     goto FAILURE
  4911.                     
  4912.             end
  4913.  
  4914.         COMMIT TRAN 
  4915.  
  4916.         /* If the article status is active adding the merge triggers to the base table */
  4917.          
  4918.         return (0)
  4919. FAILURE:
  4920.         RAISERROR (20009, 16, -1, @article, @publication)
  4921.         if @@TRANCOUNT > 0
  4922.         begin
  4923.             ROLLBACK TRANSACTION sp_addmergearticle
  4924.             COMMIT TRANSACTION
  4925.         end
  4926.         return (1)
  4927. go
  4928.  
  4929. exec dbo.sp_MS_marksystemobject sp_addmergearticle
  4930. go
  4931.  
  4932. grant execute on dbo.sp_addmergearticle to public
  4933. go
  4934.  
  4935. raiserror('Creating procedure sp_MSchangemergeschemaarticle', 0,1)
  4936. GO
  4937.  
  4938. CREATE PROCEDURE sp_MSchangemergeschemaarticle (
  4939.     @pubid uniqueidentifier,
  4940.     @artid uniqueidentifier,
  4941.     @property sysname,
  4942.     @value nvarchar(2000)
  4943.     ) AS
  4944.     
  4945.     set nocount on
  4946.  
  4947.     /*
  4948.     ** No need to bump the compatibility level
  4949.     ** here as the compatibility level for
  4950.     ** a publication with a schema-only article 
  4951.     ** is already 80
  4952.     */
  4953.     declare @schema_option   binary(8)
  4954.     declare @precmdid        tinyint
  4955.     declare @creation_script nvarchar(255)
  4956.     declare @statusid        tinyint
  4957.     declare @type            tinyint
  4958.     declare @source_object   sysname
  4959.     declare @valid_schema_options int
  4960.  
  4961.     /* 
  4962.     ** Parameter Check: @property
  4963.     ** Check to make sure that @property is a valid property in 
  4964.     ** sysmergeschemaarticles.
  4965.     */
  4966.     select @property = lower(@property collate SQL_Latin1_General_CP1_CS_AS)
  4967.     if @property NOT IN ('description',
  4968.                          'pre_creation_command',
  4969.                          'creation_script',
  4970.                          'status',
  4971.                          'schema_option',
  4972.                          'destination_owner',
  4973.                          'destination_object')
  4974.     begin
  4975.         raiserror(21224, 16, -1, @property)
  4976.         return (1)
  4977.     end  
  4978.  
  4979.     select @type = type, @source_object = object_name(objid)
  4980.       from sysmergeextendedarticlesview
  4981.      where pubid = @pubid
  4982.        and artid = @artid 
  4983.  
  4984.     -- Since all property changes will take the form of 
  4985.     -- simple update stataments, no transaction will be 
  4986.     -- started. 
  4987.  
  4988.     if @property = N'description'
  4989.     begin
  4990.         update sysmergeschemaarticles 
  4991.            set description = @value 
  4992.          where pubid = @pubid
  4993.            and artid = @artid
  4994.             
  4995.         if @@error <> 0
  4996.             return 1
  4997.     end
  4998.     else if @property = N'pre_creation_command'
  4999.     begin
  5000.         /*
  5001.         ** The value for the pre_creation_command
  5002.         ** property must be either 'none' or 'drop'  
  5003.         */
  5004.         select @value = lower(@value collate SQL_Latin1_General_CP1_CS_AS)
  5005.         if @value not in (N'none', N'drop')
  5006.         begin
  5007.             raiserror(21223, 16, -1)
  5008.             return (1)
  5009.         end
  5010.  
  5011.         if @value = N'none'
  5012.             select @precmdid = 0
  5013.         else if @value = N'drop'
  5014.             select @precmdid = 1 
  5015.             
  5016.         update sysmergeschemaarticles
  5017.            set pre_creation_command = @precmdid
  5018.          where pubid = @pubid
  5019.            and artid = @artid
  5020.  
  5021.         if @@error <> 0
  5022.             return (1)
  5023.  
  5024.     end   
  5025.     else if @property = N'creation_script'
  5026.     begin
  5027.         if @value is NULL or @value = N''
  5028.         begin
  5029.             /*
  5030.             ** Existing schema option must not be 
  5031.             ** 0x0000000000000000 if the creation_script 
  5032.             ** path has to be set to null
  5033.             */
  5034.  
  5035.             select @schema_option = schema_option from sysmergeschemaarticles
  5036.             where pubid = @pubid and artid = @artid
  5037. /*            
  5038.             if @schema_option = 0x0000000000000000
  5039.             begin
  5040.                 raiserror(21218, 16, -1)
  5041.                 return (1)
  5042.             end
  5043. */
  5044.  
  5045.         end
  5046.  
  5047.         update sysmergeschemaarticles 
  5048.            set creation_script = @value
  5049.          where pubid = @pubid 
  5050.            and artid = @artid     
  5051.  
  5052.         if @@error <> 0
  5053.             return (1)
  5054.  
  5055.     end 
  5056.     else if @property = N'status'
  5057.     begin
  5058.         select @value = lower(@value collate SQL_Latin1_General_CP1_CS_AS)
  5059.  
  5060.         if @value not in ('active', 'unsynced')
  5061.         begin
  5062.             raiserror(20075, 16, -1)
  5063.             return (1)
  5064.         end
  5065.  
  5066.         if @value = N'unsynced'
  5067.             select @statusid = 1
  5068.         else if @value = N'active'
  5069.             select @statusid = 2
  5070.  
  5071.         update sysmergeschemaarticles
  5072.            set status = @statusid 
  5073.          where pubid = @pubid
  5074.            and artid = @artid
  5075.         
  5076.         if @@error <> 0
  5077.             return (1)
  5078.     end
  5079.     else if @property = N'schema_option'
  5080.     begin
  5081.        
  5082.         if @value is null
  5083.         begin
  5084.             raiserror(14146, 16,1)
  5085.             return (1)
  5086.         end
  5087.  
  5088.         create table #tab_changeschemaarticle (value varbinary(8) NULL)
  5089.         if @@error <> 0
  5090.         begin
  5091.             return(1)
  5092.         end
  5093.     
  5094.         exec ('insert #tab_changeschemaarticle values (' + 
  5095.             @value + ')')    
  5096.     
  5097.         if @@error <> 0
  5098.         begin
  5099.             drop table #tab_changeschemaarticle    
  5100.             return (1)
  5101.         end
  5102.     
  5103.         select @schema_option = fn_replprepadbinary8(value) 
  5104.           from #tab_changeschemaarticle
  5105.      
  5106.         /*
  5107.         ** schema_option can only contain the bits 0x0000000000000001 and
  5108.         ** 0x0000000000002000
  5109.         ** for schema only articles except view. View articles can contain 
  5110.         ** the options 0x0000000000000010, 0x0000000000000020, and 0x0000000000000100 
  5111.         ** in addition to the aforementioned options.
  5112.         */
  5113.         if @type = 0x40
  5114.         begin
  5115.  
  5116.             -- Since only the lower 32 bits of @schema_option are
  5117.             -- currently, the following check is sufficient.
  5118.             declare @schema_option_lodword int
  5119.             select @valid_schema_options = 0x2151
  5120.             select @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  5121.             if (@schema_option_lodword & ~@valid_schema_options) <> 0
  5122.             begin
  5123.                 raiserror (21229, 16, -1)
  5124.                 return (1)
  5125.             end
  5126.         end
  5127.         else if @schema_option not in (0x0000000000000000,
  5128.                                        0x0000000000000001,
  5129.                                        0x0000000000002000,
  5130.                                        0x0000000000002001)
  5131.         begin
  5132.             drop table #tab_changeschemaarticle 
  5133.             raiserror (21222, 16, -1)
  5134.             return (1)
  5135.         end
  5136.  
  5137.         if exists (select * from #tab_changeschemaarticle 
  5138.                     where value = 0x0000000000000000)
  5139.         begin
  5140.  
  5141.             select @creation_script = NULL
  5142.             select @creation_script = creation_script 
  5143.               from sysmergeschemaarticles
  5144.              where pubid = @pubid
  5145.                and artid = @artid
  5146. /*            
  5147.             if @creation_script is NULL or 
  5148.                @creation_script = N''
  5149.             begin
  5150.                 raiserror(21218, 16, -1) 
  5151.                 drop table #tab_changeschemaarticle    
  5152.                 return (1)
  5153.             end
  5154. */
  5155.         end 
  5156.             
  5157.         update sysmergeschemaarticles
  5158.            set schema_option = fn_replprepadbinary8(tab.value)
  5159.           from #tab_changeschemaarticle tab
  5160.          where pubid = @pubid 
  5161.            and artid = @artid
  5162.         
  5163.         if @@error <> 0
  5164.         begin
  5165.             drop table #tab_changeschemaarticle    
  5166.             return (1)
  5167.         end
  5168.  
  5169.         drop table #tab_changeschemaarticle    
  5170.             
  5171.         if @@error <> 0
  5172.             return (1)
  5173.     end
  5174.     else if @property = N'destination_owner'
  5175.     begin
  5176.         select @value = rtrim(@value) 
  5177.         update sysmergeschemaarticles 
  5178.            set destination_owner = @value
  5179.          where pubid = @pubid
  5180.            and artid = @artid
  5181.         
  5182.         if @@error <> 0
  5183.             return (1)
  5184.     end
  5185.     else if @property = N'destination_object'
  5186.     begin
  5187.         select @value = rtrim(@value) 
  5188.         if @value is null or @value = ''
  5189.         begin
  5190.             select @value = @source_object
  5191.         end
  5192.         update sysmergeschemaarticles
  5193.            set destination_object = @value
  5194.          where pubid = @pubid
  5195.            and artid = @artid        
  5196.     end
  5197.  
  5198.     return (0)        
  5199.  
  5200. go
  5201.  
  5202. exec dbo.sp_MS_marksystemobject sp_MSchangemergeschemaarticle
  5203. go
  5204.  
  5205. raiserror('Creating procedure sp_changemergearticle', 0,1)
  5206. GO
  5207.  
  5208. CREATE PROCEDURE sp_changemergearticle (
  5209.     @publication sysname,              /* Publication name */
  5210.     @article sysname,              /* Article name */
  5211.     @property sysname = NULL,          /* The property to change */
  5212.     @value nvarchar(2000) = NULL,             /* The new property value */
  5213.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  5214.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  5215.     ) AS
  5216.  
  5217.     SET NOCOUNT ON
  5218.  
  5219.     /*
  5220.     ** Declarations.
  5221.     */
  5222.     declare @sp_resolver            sysname
  5223.     declare @db_name            sysname
  5224.     declare @intvalue            bigint
  5225.     declare @artid              uniqueidentifier
  5226.     declare @pubid              uniqueidentifier
  5227.     declare @artidstr           nvarchar(38)
  5228.     declare @object_view        sysname
  5229.     declare @vertical            int
  5230.     declare @pubidstr           nvarchar(38)
  5231.     declare @object             sysname
  5232.     declare @owner              sysname
  5233.     declare @identity_support     int
  5234.     declare @column_list        nvarchar(4000)
  5235.     declare @resolver_clsid     nvarchar(50)
  5236.     declare @article_resolver   nvarchar(255)
  5237.     declare @resolver_clsid_str nvarchar(55)
  5238.     declare @article_resolver_str   nvarchar(270)
  5239.     declare @value_str            nvarchar(270)
  5240.     declare @retcode            int
  5241.     declare @statusid           int
  5242.     declare @precmdid           tinyint
  5243.     declare @regkey             nvarchar(255)
  5244.     declare @distributor        sysname
  5245.     declare @distribdb        sysname
  5246.     declare @distproc           nvarchar(300)
  5247.     declare @snapshot_ready        int
  5248.     declare @schemaversion      int 
  5249.     declare @objid                int
  5250.     declare @schemaguid         uniqueidentifier
  5251.     declare @schematype         int
  5252.     declare @schematext         nvarchar(2000)
  5253.     declare @type               tinyint
  5254.     declare @allow_interactive_bit    int
  5255.     declare @additive_resolver        sysname
  5256.     declare @average_resolver        sysname
  5257.     declare @mindate_resolver        sysname
  5258.     declare @maxdate_resolver        sysname
  5259.     declare @minimum_resolver        sysname
  5260.     declare @maximum_resolver        sysname
  5261.     declare @mergetxt_resolver        sysname
  5262.     declare @pricolumn_resolver        sysname
  5263.     declare @pre_command            int
  5264.     declare @coltrack                int
  5265.  
  5266.     declare @qual_object_view        nvarchar(140)
  5267.     declare @qual_object            nvarchar(140)
  5268.     declare @quoted_object            nvarchar(140)
  5269.     declare @bump_to_80             bit
  5270.     declare @schema_option          binary(8)
  5271.     declare @old_schema_option      binary(8)
  5272.  
  5273.     /*
  5274.     ** Security Check
  5275.     */
  5276.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  5277.     IF @@ERROR <> 0 or @retcode <> 0
  5278.         return (1)
  5279.  
  5280.     select @db_name = db_name()
  5281.     select @bump_to_80 = 0
  5282.  
  5283.     /*
  5284.     ** Check to see if the database has been activated for publication.
  5285.     */
  5286.  
  5287.     if (select category & 4
  5288.           FROM master..sysdatabases
  5289.          WHERE name = @db_name collate database_default) = 0
  5290.  
  5291.     BEGIN
  5292.         RAISERROR (14013, 16, -1)
  5293.         RETURN (1)
  5294.     END
  5295.  
  5296.     /*
  5297.     ** Parameter Check:  @publication.
  5298.     ** Make sure that the publication exists.
  5299.     */
  5300.  
  5301.     if @publication IS NULL
  5302.         BEGIN
  5303.             RAISERROR (14043, 16, -1, '@publication')
  5304.             RETURN (1)
  5305.         END
  5306.  
  5307.     select @pubid = pubid, @snapshot_ready=snapshot_ready from sysmergepublications 
  5308.         where name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=@db_name
  5309.     if @pubid IS NULL
  5310.         BEGIN
  5311.             RAISERROR (20026, 16, -1, @publication)
  5312.             RETURN (1)
  5313.         END
  5314.     
  5315.     select @db_name = db_name from sysmergesubscriptions
  5316.         where (pubid=@pubid) and (subid=@pubid)
  5317.         IF @db_name <> @db_name
  5318.         BEGIN
  5319.             RAISERROR (20047, 16, -1)
  5320.             RETURN (1)
  5321.         END
  5322.  
  5323.     /*
  5324.     ** Parameter Check:  @property.
  5325.     ** If the @property parameter is NULL, print the options.
  5326.     */
  5327.  
  5328.     if @property IS NULL
  5329.         BEGIN
  5330.             CREATE TABLE #tab1 (properties sysname collate database_default)
  5331.             INSERT INTO #tab1 VALUES ('description')
  5332.             INSERT INTO #tab1 VALUES ('pre_creation_command')
  5333.             INSERT INTO #tab1 VALUES ('creation_script')
  5334.             INSERT INTO #tab1 VALUES ('column_tracking (table article only)')
  5335.             INSERT INTO #tab1 VALUES ('article_resolver (table article only)')
  5336.             INSERT INTO #tab1 VALUES ('resolver_info (table article only)')
  5337.             INSERT INTO #tab1 VALUES ('status')
  5338.             INSERT INTO #tab1 VALUES ('subset_filterclause (table article only)')
  5339.             INSERT INTO #tab1 VALUES ('schema_option')
  5340.             INSERT INTO #tab1 VALUES ('destination_owner')
  5341.                INSERT INTO #tab1 VALUES ('pub_identity_range (table article only)')
  5342.             INSERT INTO #tab1 VALUES ('identity_range (table article only)')
  5343.             INSERT INTO #tab1 VALUES ('threshold (table article only)')
  5344.             INSERT INTO #tab1 VALUES ('verify_resolver_signature')
  5345.             INSERT INTO #tab1 VALUES ('allow_interactive_resolver')
  5346.             INSERT INTO #tab1 VALUES ('check_permissions')
  5347.             select * FROM #tab1
  5348.             RETURN (0)
  5349.         END
  5350.  
  5351.     /*
  5352.     ** Check to see that the article exists in sysmergearticles.
  5353.     ** Fetch the article identification number.
  5354.     */
  5355.  
  5356.     if @article IS NULL
  5357.         BEGIN
  5358.             RAISERROR (14043, 16, -1, '@article')
  5359.             RETURN (1)
  5360.         END
  5361.  
  5362.     select @artid = artid, 
  5363.            @type = type,
  5364.            @old_schema_option = schema_option,
  5365.            @objid = objid
  5366.      FROM sysmergeextendedarticlesview
  5367.         WHERE name = @article AND pubid = @pubid
  5368.     if @artid IS NULL
  5369.         BEGIN
  5370.             RAISERROR (20027, 16, -1, @article)
  5371.             RETURN (1)
  5372.         END
  5373.  
  5374.     select @pre_command=pre_creation_command, @identity_support = identity_support from sysmergearticles where pubid=@pubid and artid=@artid
  5375.     /*
  5376.     ** Handle the changing of schema only articles property
  5377.     ** in a different procedure
  5378.     */
  5379.     if @type in (0x20, 0x40, 0x80)
  5380.         begin
  5381.             exec @retcode = sp_MSchangemergeschemaarticle @pubid = @pubid,
  5382.                                                            @artid = @artid,
  5383.                                                            @property = @property,
  5384.                                                            @value = @value
  5385.             return @retcode
  5386.         end             
  5387.  
  5388.     /*
  5389.     ** Parameter Check:  @property.
  5390.     ** Check to make sure that @property is a valid property in
  5391.     ** sysmergearticles.
  5392.     */
  5393.     if @property IS NULL OR LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT in 
  5394.                                                     ('name',
  5395.                                                      'description',
  5396.                                                      'pre_creation_command',
  5397.                                                      'creation_script',
  5398.                                                      'column_tracking',
  5399.                                                      'article_resolver',    
  5400.                                                      'resolver_info',
  5401.                                                      'status',
  5402.                                                      'subset_filterclause',
  5403.                                                      'schema_option',
  5404.                                                      'pub_identity_range',
  5405.                                                      'identity_range',
  5406.                                                      'threshold',
  5407.                                                      'verify_resolver_signature',
  5408.                                                      'check_permissions',
  5409.                                                      'allow_interactive_resolver',
  5410.                                                      'destination_owner')
  5411.         BEGIN
  5412.             RAISERROR (21259, 16, -1, @property)
  5413.             RETURN (1)
  5414.         END
  5415.         
  5416.     -- COMMENT: the following article properties can not be changed at republisher side
  5417.     if    LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('article_resolver','resolver_info','column_tracking',
  5418.                     'allow_interactive_resolver','verify_resolver_signature') and 
  5419.             exists (select * from sysmergearticles where objid=@objid and pubid not in 
  5420.                 (select pubid from sysmergepublications where UPPER(publisher)=UPPER(@@servername) 
  5421.                     and publisher_db=@db_name))
  5422.         
  5423.         BEGIN
  5424.             RAISERROR(21400, 16, -1, @article)
  5425.             return (1)
  5426.         END
  5427.  
  5428.     if @identity_support=0 and LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('pub_identity_range','identity_range','threshold')
  5429.         begin
  5430.             RAISERROR(21257, 16, -1, @property, @article)
  5431.             return (1)
  5432.         end
  5433.  
  5434.     exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  5435.                        @distribdb   = @distribdb OUTPUT
  5436.     IF @@ERROR <> 0 or @retcode <> 0 or @distributor is NULL
  5437.     BEGIN
  5438.         RAISERROR (20036, 16, -1)
  5439.         RETURN (1)
  5440.     END
  5441.  
  5442.     SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadjust_pub_identity'
  5443.     select @objid=objid, @object = object_name(objid), @vertical=vertical_partition from sysmergearticles where artid=@artid and pubid=@pubid
  5444.     set @artidstr = '''' + convert(nchar(36), @artid) + '''' 
  5445.     set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' 
  5446.     select @sp_resolver         = 'Microsoft SQLServer Stored Procedure Resolver'
  5447.     select @additive_resolver     = 'Microsoft SQL Server Additive Conflict Resolver'
  5448.     select @average_resolver     = 'Microsoft SQL Server Averaging Conflict Resolver'
  5449.     select @minimum_resolver     = 'Microsoft SQL Server Minimum Conflict Resolver'
  5450.     select @maximum_resolver     = 'Microsoft SQL Server Maximum Conflict Resolver'
  5451.     select @mindate_resolver     = 'Microsoft SQL Server DATETIME (Earlier Wins) Conflict Resolver'
  5452.     select @maxdate_resolver     = 'Microsoft SQL Server DATETIME (Later Wins) Conflict Resolver'
  5453.     select @mergetxt_resolver     = 'Microsoft SQL Server Merge Text Columns Conflict Resolver'
  5454.     select @pricolumn_resolver     = 'Microsoft SQL Server Priority Column Resolver'
  5455.  
  5456.     BEGIN TRAN
  5457.     save TRAN changemergearticle
  5458.     /*
  5459.     ** Changing of the following properties would require a snapshot rerun.and reinit, if snapshot is ready
  5460.     */
  5461.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in 
  5462.                                                     ('pre_creation_command',
  5463.                                                      'creation_script',
  5464.                                                      'column_tracking',
  5465.                                                      'subset_filterclause',
  5466.                                                      'schema_option',
  5467.                                                      'destination_owner',
  5468.                                                      'check_permissions')
  5469.         and    @snapshot_ready > 0
  5470.     begin
  5471.         if @pre_command<>1 -- 1 means'drop': which is the only option that support reintialization
  5472.         begin
  5473.             raiserror(21416, 16, -1, @property, @article)
  5474.             goto UNDO            
  5475.         end
  5476.         if @force_invalidate_snapshot = 0
  5477.         begin
  5478.             raiserror(20607, 16, -1)
  5479.             goto UNDO
  5480.         end
  5481.         if @force_reinit_subscription = 0
  5482.         begin
  5483.             raiserror(20608, 16, -1)
  5484.             goto UNDO
  5485.         end
  5486.         
  5487.         update sysmergepublications set snapshot_ready=2 where pubid=@pubid and snapshot_ready=1
  5488.         if @@ERROR<>0    
  5489.             GOTO UNDO
  5490.         exec @retcode=sp_MSreinitmergepublication @publication
  5491.         if @@ERROR<>0 or @retcode<>0
  5492.             GOTO UNDO 
  5493.     end
  5494.  
  5495.     /*
  5496.     ** Change the property.
  5497.     */
  5498.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'column_tracking'
  5499.         BEGIN
  5500.             /*
  5501.             ** Check to make sure that we have a valid type.
  5502.             */
  5503.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  5504.                 BEGIN
  5505.                     RAISERROR (14137, 16, -1)
  5506.                     goto UNDO
  5507.                 END
  5508.  
  5509.             /*
  5510.             ** Update the syssubsetdefintions table with the new column tracking.
  5511.             */
  5512.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  5513.                     update sysmergearticles set column_tracking = 1 where artid=@artid      
  5514.             else
  5515.                     update sysmergearticles set column_tracking = 0 where artid=@artid
  5516.             if @@ERROR <> 0 
  5517.                 goto UNDO
  5518.  
  5519.         END
  5520.  
  5521.     
  5522.     /* pub_identity_range is not stored at distribution database because it is not interested in this value.*/   
  5523.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pub_identity_range'
  5524.         BEGIN
  5525.             select @intvalue = convert(bigint, @value)
  5526.             if @intvalue<0
  5527.             begin
  5528.                 raiserror(21232, 16, -1)
  5529.                 goto UNDO
  5530.             end
  5531.             update MSrepl_identity_range set pub_range=@intvalue where objid=@objid
  5532.             if @@ERROR<>0
  5533.                 goto UNDO        
  5534.         END
  5535.      
  5536.     /* the property of check permissions is a bitmask of which operation do we want to check for*/   
  5537.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'check_permissions'
  5538.         BEGIN
  5539.             select @intvalue = convert(int, @value)
  5540.             if @intvalue<0
  5541.             begin
  5542.                 raiserror(21232, 16, -1)
  5543.                 goto UNDO
  5544.             end
  5545.             update sysmergearticles set check_permissions=@intvalue
  5546.             if @@ERROR<>0
  5547.                 goto UNDO        
  5548.         END
  5549.  
  5550.  
  5551.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'identity_range'
  5552.         BEGIN
  5553.             select @intvalue = convert(bigint, @value)
  5554.             if @intvalue<0
  5555.             begin
  5556.                 raiserror(21232, 16, -1)
  5557.                 goto UNDO
  5558.             end
  5559.  
  5560.             update MSrepl_identity_range set range=@intvalue where objid=@objid
  5561.             if @@ERROR<>0
  5562.                 goto UNDO
  5563.             exec  @retcode=@distproc @publisher=@@SERVERNAME,
  5564.                                         @publisher_db=@db_name,
  5565.                                         @tablename=@object,
  5566.                                         @range=@intvalue
  5567.                 if @retcode<>0 or @@ERROR<>0
  5568.                     goto UNDO
  5569.  
  5570.         END
  5571.  
  5572.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'threshold'
  5573.         BEGIN
  5574.             select @intvalue = convert(int, @value)
  5575.             if @intvalue<0 or @intvalue>100
  5576.             begin
  5577.                 raiserror(21241, 16, -1)
  5578.                 goto UNDO
  5579.             end
  5580.             update MSrepl_identity_range set threshold=@intvalue where objid=@objid
  5581.             if @@ERROR<>0
  5582.                 goto UNDO
  5583.             exec  @retcode=@distproc @publisher=@@SERVERNAME,
  5584.                                         @publisher_db=@db_name,
  5585.                                         @tablename=@object,
  5586.                                         @threshold=@intvalue
  5587.                 if @retcode<>0 or @@ERROR<>0
  5588.                     goto UNDO
  5589.  
  5590.         END
  5591.  
  5592.      if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='description'
  5593.         BEGIN
  5594.         UPDATE sysmergearticles  SET description = @value WHERE artid = @artid and pubid = @pubid
  5595.             AND pubid = @pubid
  5596.         if @@ERROR <> 0 
  5597.                 goto UNDO
  5598.     END
  5599.  
  5600.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) ='creation_script'
  5601.         BEGIN
  5602.             update sysmergearticles set creation_script=@value where artid=@artid and pubid=@pubid
  5603.             if @@ERROR <> 0 
  5604.                 goto UNDO
  5605.         END
  5606.  
  5607.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'subset_filterclause'
  5608.         BEGIN
  5609.             if @value is not null and @value<>''
  5610.             begin
  5611.             /* check the validity of subset_filterclause */
  5612.             select @object_view=@object
  5613.             select @quoted_object=QUOTENAME(@object)    
  5614.             
  5615.             exec @retcode = sp_MSget_qualified_name @objid, @qual_object OUTPUT
  5616.             if @@ERROR<>0 or @retcode<>0
  5617.                 goto UNDO
  5618.             select @qual_object_view=@qual_object
  5619.             
  5620.             if @vertical=1
  5621.             begin
  5622.               select @object_view='TEMP_VIEW_' + @object
  5623.               select @qual_object_view = QUOTENAME(@object_view)
  5624.               exec @retcode = sp_MSgetcolumnlist @pubid, @column_list OUTPUT, @objid
  5625.               exec ('create view ' + @qual_object_view + ' as select ' + @column_list + ' from ' + @quoted_object)
  5626.               if @@ERROR<>0
  5627.               begin
  5628.                   raiserror(21256, 16, -1, @value, @object)
  5629.                 goto UNDO
  5630.               end
  5631.             end
  5632.             
  5633.             exec ('declare @test int select @test=1 from ' + @qual_object_view + ' ' + @quoted_object + ' where ' + @value)
  5634.             if @@ERROR<>0
  5635.                 begin
  5636.                     if @vertical=1
  5637.                         exec('drop view ' + @qual_object_view)
  5638.                     raiserror(21256, 16, -1, @value, @object)
  5639.                     goto UNDO
  5640.                 end
  5641.             end
  5642.             if @vertical=1
  5643.                 exec('drop view ' + @qual_object_view)
  5644.  
  5645.             update sysmergearticles set subset_filterclause = @value where artid=@artid and pubid=@pubid
  5646.             if @@ERROR<>0 goto UNDO
  5647.             
  5648.             /*
  5649.             ** set the pub type to subset or full as appropriate
  5650.             */
  5651.             execute @retcode = dbo.sp_MSsubsetpublication @publication
  5652.             if @@ERROR <> 0 OR @retcode <> 0
  5653.                 goto UNDO
  5654.                 
  5655.         END
  5656.  
  5657.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) ='article_resolver'
  5658.         BEGIN
  5659.  
  5660.             if @value IS NULL OR @value = 'default' OR @value = ''
  5661.                 begin
  5662.                     set @article_resolver = NULL
  5663.                     set @resolver_clsid = NULL
  5664.                 end                 
  5665.                     
  5666.             else
  5667.                 begin
  5668.                     EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
  5669.                                       'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver',
  5670.                                       @value,
  5671.                                       @param = @resolver_clsid OUTPUT
  5672.                     IF @@ERROR <> 0 or @retcode <> 0 or @resolver_clsid IS NULL
  5673.                         BEGIN
  5674.                             RAISERROR (20020, 16, -1)
  5675.                             goto UNDO
  5676.                         END
  5677.                 end                     
  5678.                     
  5679.             /*
  5680.             ** Update the appropriate column in sysmergearticles with the new article resolver name.
  5681.             ** Note this could affect multiple publication if the same table spans publications
  5682.             */
  5683.  
  5684.             /* NOTE: new change */
  5685.                 exec @retcode = dbo.sp_MSchangearticleresolver @value, @resolver_clsid, @artid
  5686.                 if @@ERROR <> 0 OR @retcode <> 0
  5687.                     begin
  5688.                         goto UNDO                          
  5689.                     end  
  5690.                 
  5691.                 declare one_pub CURSOR LOCAL FAST_FORWARD FOR 
  5692.                     select DISTINCT pubid from sysmergearticles where artid=@artid
  5693.                 FOR READ ONLY
  5694.                 open one_pub
  5695.                 fetch next from one_pub into @pubid
  5696.                  
  5697.                 while (@@fetch_status <> -1)
  5698.                     begin
  5699.                         select @snapshot_ready=snapshot_ready from sysmergepublications 
  5700.                             where pubid = @pubid
  5701.                         /* Insert the sp_MSchangearticleresolver schema change only if the publication's snapshot is ready */
  5702.                         if (@snapshot_ready > 0)
  5703.                             begin
  5704.                                 select @schemaversion = schemaversion from sysmergeschemachange
  5705.                                 if (@schemaversion is NULL) 
  5706.                                     set @schemaversion = 1
  5707.                                 else  
  5708.                                     select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  5709.                                 set @schemaguid = newid()
  5710.                                 set @schematype = 8
  5711.                                 if @value is not NULL and @value <> ''
  5712.                                     select @schematext = 'exec dbo.sp_MSchangearticleresolver ' + quotename(@value) + ',' + '''' + @resolver_clsid + '''' + ',' + '''' + convert(nchar(36), @artid) + ''''
  5713.                                 else
  5714.                                     select @schematext = 'exec dbo.sp_MSchangearticleresolver NULL, NULL,' + '''' + convert(nchar(36), @artid) + ''''
  5715.                                      
  5716.                                 exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext 
  5717.                                 if @@ERROR <> 0 OR @retcode <> 0
  5718.                                     goto UNDO
  5719.                             end                                        
  5720.                         fetch next from one_pub into @pubid
  5721.                     end 
  5722.                 close one_pub
  5723.                 deallocate one_pub
  5724.  
  5725.         END /* for property = 'article_resolver' */
  5726.  
  5727.  
  5728.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) ='resolver_info'
  5729.         BEGIN
  5730.             /* allow non-sp's as resolver info; don't change the resolver class */
  5731.             select     @article_resolver = article_resolver, 
  5732.                     @resolver_clsid = resolver_clsid from
  5733.                     sysmergearticles where artid = @artid
  5734.  
  5735.             -- Convert NULL value to 'NULL' string to be used for constructing schema text
  5736.             -- we do not want to change NULL value to ''.
  5737.             select @article_resolver_str=QUOTENAME(@article_resolver)
  5738.             select @resolver_clsid_str = @resolver_clsid
  5739.             select @value_str=@value
  5740.             if @article_resolver is null set @article_resolver_str = 'NULL'
  5741.             if @resolver_clsid is null set @resolver_clsid_str = 'NULL'
  5742.             if @value is null set @value_str = 'NULL'
  5743.  
  5744.             /* The following resolvers expect the @resolver_info to be NON NULL */
  5745.             if  @article_resolver = @sp_resolver or 
  5746.                 @article_resolver = @additive_resolver or
  5747.                 @article_resolver = @average_resolver or
  5748.                 @article_resolver = @minimum_resolver or
  5749.                 @article_resolver = @maximum_resolver or
  5750.                 @article_resolver = @mindate_resolver or
  5751.                 @article_resolver = @maxdate_resolver or
  5752.                 @article_resolver = @mergetxt_resolver or
  5753.                 @article_resolver = @pricolumn_resolver
  5754.                 begin
  5755.                     if @value IS NULL or @value = ''
  5756.                         begin
  5757.                             RAISERROR (21301, 16, -1, @article_resolver)
  5758.                             goto UNDO
  5759.                         end
  5760.                 end
  5761.  
  5762.             /* The SP resolver expect the @resolver_info to be the name of sp */
  5763.             if  @article_resolver = @sp_resolver
  5764.                 begin
  5765.                     if not exists (select * from sysobjects where id = object_id(@value) and ( type = 'P' or type = 'X'))
  5766.                         begin
  5767.                             raiserror(21343, 16, -1, @value)
  5768.                             goto UNDO
  5769.                         end
  5770.                 end
  5771.             /*
  5772.             ** If article resolver is 'mindate/maxdate resolver', make sure that resolver_info refers to a column that is of datatype 'datetime' or smalldatetime
  5773.             */
  5774.             if  @article_resolver = @mindate_resolver or
  5775.                 @article_resolver = @maxdate_resolver
  5776.                 begin
  5777.                     if not exists (select * from syscolumns where id = @objid and name=@value and type_name(xtype)='datetime' or type_name(xtype) = 'smalldatetime' )
  5778.                         begin
  5779.                             RAISERROR (21302, 16, -1, @article_resolver)
  5780.                             goto UNDO
  5781.                         end
  5782.                 end
  5783.  
  5784.             /* The following resolvers expect the article to be column trcaked - warn that the default resolver migh be used */
  5785.             if  @article_resolver = @additive_resolver or
  5786.                 @article_resolver = @average_resolver
  5787.                 begin
  5788.                     select @coltrack = column_tracking from sysmergearticles where artid = @artid
  5789.                     if @coltrack = 0
  5790.                         begin
  5791.                             RAISERROR (21303, 10, -1, @article, @article_resolver)
  5792.                         end
  5793.                         
  5794.                 end
  5795.                 
  5796.  
  5797.             /*
  5798.             ** Update the appropriate column in sysmergearticles with the new resolver info.
  5799.             ** Note this could affect multiple publication if the same table spans publications
  5800.             */
  5801.                 exec @retcode = dbo.sp_MSchangearticleresolver @article_resolver, @resolver_clsid, @artid, @value
  5802.                 if @@ERROR <> 0 OR @retcode <> 0
  5803.                     begin
  5804.                         goto UNDO                          
  5805.                     end         
  5806.                 declare one_pub CURSOR LOCAL FAST_FORWARD FOR 
  5807.                     select DISTINCT pubid from sysmergearticles where artid=@artid
  5808.                 FOR READ ONLY
  5809.                 open one_pub
  5810.                 fetch next from one_pub into @pubid
  5811.                  
  5812.                 while (@@fetch_status <> -1)
  5813.                     begin
  5814.                         select @snapshot_ready=snapshot_ready from sysmergepublications 
  5815.                             where pubid = @pubid
  5816.                         /* Insert the sp_MSchangearticleresolver schema change only if the publication's snapshot is ready */
  5817.                         if (@snapshot_ready > 0)
  5818.                             begin
  5819.                                 select @schemaversion = schemaversion from sysmergeschemachange
  5820.                                 if (@schemaversion is NULL) set @schemaversion = 1
  5821.                                 else  
  5822.                                     select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  5823.                                 set @schemaguid = newid()
  5824.                                 set @schematype = 8
  5825.                                 select @schematext = 'exec dbo.sp_MSchangearticleresolver ' + @article_resolver_str + ',' + '''' + @resolver_clsid_str + '''' + ',' + '''' + convert(nchar(36), @artid) + '''' + ',' + '''' + @value_str + ''''
  5826.                                  
  5827.                                 exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext 
  5828.                                 if @@ERROR <> 0 OR @retcode <> 0
  5829.                                     begin
  5830.                                         goto UNDO                          
  5831.                                     end
  5832.                             end                             
  5833.                         fetch next from one_pub into @pubid
  5834.                     end 
  5835.                 close one_pub
  5836.                 deallocate one_pub
  5837.  
  5838.         END /* for property = 'resolver_info' */
  5839.  
  5840.  
  5841.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pre_creation_command'
  5842.         BEGIN
  5843.  
  5844.             /*
  5845.             ** Check to make sure that we have a valid pre_creation_cmd.
  5846.             */
  5847.  
  5848.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop', 'delete', 'truncate')
  5849.                 BEGIN
  5850.                     RAISERROR (14061, 16, -1)
  5851.                     goto UNDO
  5852.                 END
  5853.  
  5854.             /*
  5855.             ** Determine the integer value for the pre_creation_cmd.
  5856.             */
  5857.  
  5858.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'none'
  5859.                 select @precmdid = 0
  5860.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  5861.                 select @precmdid = 1
  5862.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'delete'
  5863.                 select @precmdid = 2
  5864.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'truncate'
  5865.                 select @precmdid = 3
  5866.  
  5867.             /*
  5868.             ** Update the article with the new pre_creation_cmd.
  5869.             */
  5870.             UPDATE sysmergearticles
  5871.                 SET pre_creation_command = @precmdid
  5872.                 WHERE artid = @artid
  5873.                 AND pubid = @pubid
  5874.  
  5875.             if @@ERROR <> 0 
  5876.                 goto UNDO
  5877.  
  5878.         END
  5879.  
  5880.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status'
  5881.         BEGIN
  5882.  
  5883.             /*
  5884.             ** Check to make sure that we have a valid status
  5885.             */
  5886.  
  5887.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('active', 'unsynced', 'new_inactive', 'new_active')
  5888.                 BEGIN
  5889.                     RAISERROR (20075, 16, -1)
  5890.                     goto UNDO
  5891.                 END
  5892.  
  5893.             /*
  5894.             ** Determine the integer value for the type.
  5895.             */
  5896.  
  5897.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'unsynced'
  5898.                 select @statusid = 1
  5899.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'active'
  5900.                 select @statusid = 2
  5901.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'new_inactive'
  5902.                 select @statusid = 5
  5903.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'new_active'
  5904.                 select @statusid = 6
  5905.  
  5906.             /*
  5907.             ** Update the article with the new type. The same base table might be 
  5908.             ** in multiple publications - so qualify  with pubid.
  5909.             */
  5910.             UPDATE sysmergearticles
  5911.                 SET status = @statusid
  5912.                 WHERE artid = @artid and pubid = @pubid
  5913.  
  5914.             if @@ERROR <> 0 
  5915.                 goto UNDO
  5916.  
  5917.         END
  5918.  
  5919.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'destination_owner'
  5920.         BEGIN
  5921.             IF @value IS NULL or @value=''
  5922.                 select @value = 'dbo'                      
  5923.             UPDATE sysmergearticles SET destination_owner = @value
  5924.                 WHERE artid = @artid
  5925.                 AND pubid = @pubid
  5926.             if @@ERROR <> 0
  5927.                 BEGIN
  5928.                     goto UNDO
  5929.                 END
  5930.         END
  5931.     
  5932.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'schema_option'
  5933.         BEGIN
  5934.         
  5935.             IF @value IS NULL
  5936.                 BEGIN
  5937.                     RAISERROR(14146, 16,1)
  5938.                     goto UNDO
  5939.                 END
  5940.  
  5941.             CREATE TABLE #tab_changearticle (value varbinary(8) NULL)
  5942.                                  
  5943.             IF @@ERROR <> 0 
  5944.                 BEGIN
  5945.                     goto UNDO
  5946.                 END
  5947.             
  5948.             DECLARE @insert_command nvarchar(4000)
  5949.             EXEC('insert #tab_changearticle values (' + 
  5950.                         @value +')') 
  5951.             IF @@ERROR <> 0 
  5952.                 BEGIN
  5953.                     goto UNDO
  5954.                 END
  5955.                       
  5956.             SELECT @schema_option = fn_replprepadbinary8(value) 
  5957.               FROM #tab_changearticle
  5958.  
  5959.             DECLARE @schema_option_lodword INT
  5960.             DECLARE @old_schema_option_lodword INT
  5961.             DECLARE @xprop_schema_option INT
  5962.             DECLARE @collation_schema_option INT
  5963.             SELECT @xprop_schema_option = 0x00002000
  5964.             SELECT @collation_schema_option = 0x00001000
  5965.             SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  5966.             SELECT @old_schema_option_lodword = CONVERT(INT, SUBSTRING(@old_schema_option, 5, 4))
  5967.             
  5968.             -- Raise warnings only when we are enabling the Shiloh specific
  5969.             -- options
  5970.             IF ((@old_schema_option_lodword & @collation_schema_option) = 0)
  5971.                 AND 
  5972.                ((@schema_option_lodword & @collation_schema_option) <> 0)
  5973.             BEGIN
  5974.                 RAISERROR(21389, 10, -1, @publication)
  5975.                 SELECT @bump_to_80 = 1
  5976.             END
  5977.             
  5978.             IF((@old_schema_option_lodword & @xprop_schema_option) = 0)
  5979.               AND 
  5980.               ((@schema_option_lodword & @xprop_schema_option) <> 0)
  5981.             BEGIN
  5982.                 RAISERROR(21390, 10, -1, @publication)
  5983.                 SELECT @bump_to_80 = 1
  5984.             END
  5985.  
  5986.             UPDATE sysmergearticles 
  5987.                SET schema_option = fn_replprepadbinary8(tab.value) from 
  5988.                 #tab_changearticle tab 
  5989.                 WHERE artid = @artid
  5990.                 AND pubid = @pubid
  5991.             if @@ERROR <> 0
  5992.                 BEGIN
  5993.                 DROP TABLE #tab_changearticle 
  5994.                 goto UNDO
  5995.                 END
  5996.                 
  5997.             DROP TABLE #tab_changearticle 
  5998.                                  
  5999.             IF @@ERROR <> 0 
  6000.                 BEGIN
  6001.                     goto UNDO
  6002.                 END
  6003.  
  6004.         END
  6005.  
  6006.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'verify_resolver_signature'
  6007.         BEGIN
  6008.             if @value NOT IN ('1', '0')
  6009.                 BEGIN
  6010.                     raiserror(21344, 16, -1, '"verify_resolver_signature"')
  6011.                     goto UNDO
  6012.                 END
  6013.  
  6014.             update sysmergearticles set verify_resolver_signature = convert(int, @value) 
  6015.             where artid = @artid and pubid = @pubid
  6016.             if @@ERROR<>0
  6017.                 goto UNDO
  6018.         END
  6019.  
  6020.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_interactive_resolver'
  6021.         BEGIN
  6022.  
  6023.             /* Check to make sure that we have a true/false. */
  6024.  
  6025.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  6026.                 BEGIN
  6027.                     RAISERROR (14148, 16, -1, 'allow_interactive_resolver')
  6028.                     goto UNDO
  6029.                 END
  6030.  
  6031.             /* Determine the bit value. */
  6032.  
  6033.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  6034.                 SET @allow_interactive_bit = 1
  6035.             ELSE
  6036.                 SET @allow_interactive_bit = 0
  6037.     
  6038.             /* Update the subscription with the new 'allow_interactive_resolver' value. */
  6039.             update sysmergearticles set allow_interactive_resolver = @allow_interactive_bit
  6040.                 where artid = @artid and pubid = @pubid
  6041.             IF @@ERROR <> 0
  6042.                 BEGIN
  6043.                     RAISERROR (14053, 16, -1)
  6044.                     goto UNDO
  6045.                 END
  6046.  
  6047.         END
  6048.  
  6049.     IF @bump_to_80=1
  6050.     BEGIN
  6051.         EXEC @retcode = sp_MSBumpupCompLevel @pubid, 40
  6052.         IF @@ERROR<>0 or @retcode<>0
  6053.             GOTO UNDO
  6054.     END
  6055.     /*
  6056.     ** Return succeed.
  6057.     */
  6058.     COMMIT TRAN
  6059.     RETURN (0)
  6060. UNDO:
  6061.     if @@TRANCOUNT > 0
  6062.     begin
  6063.         ROLLBACK TRANSACTION changemergearticle
  6064.         COMMIT TRANSACTION
  6065.     end
  6066.     return (1)
  6067. go
  6068. exec dbo.sp_MS_marksystemobject sp_changemergearticle
  6069. go
  6070.  
  6071. grant execute on dbo.sp_changemergearticle to public
  6072. go
  6073.  
  6074.  
  6075.  
  6076.  
  6077. raiserror('Creating procedure sp_MSadjustmergeidentity', 0,1)
  6078. GO
  6079.  
  6080. /*
  6081. ** When calling from the wrapper stored procedure, we make sure that there is one and
  6082. ** only one of the two input SP is NULL. Therefore, we do no checking here.
  6083. */
  6084.  
  6085. CREATE PROCEDURE sp_MSadjustmergeidentity 
  6086. @publication        sysname = NULL,
  6087. @tablename            sysname = NULL
  6088. AS
  6089.  
  6090. declare @db_name                sysname
  6091. declare @pubid                    uniqueidentifier
  6092. declare @next_seed                bigint
  6093. declare @pub_range                bigint
  6094. declare @objid                    int
  6095. declare @qualname                nvarchar(270)
  6096. declare @retcode                int
  6097. declare @user_name                sysname        
  6098. declare @range                    bigint
  6099. declare @current_max            bigint
  6100. declare @threshold                int
  6101. declare @distributor            sysname
  6102. declare @distribdb                sysname
  6103. declare @distproc                nvarchar(300)
  6104. declare @flag                    smallint
  6105. declare @c_max                    bigint
  6106. declare @n_seed                    bigint
  6107. declare @nickname                int
  6108. declare @identity_support        int
  6109. declare @artid                    uniqueidentifier
  6110. declare @identity_so_far        bigint
  6111. declare @tablelevel                bit
  6112.  
  6113. /*
  6114. ** Security Check
  6115. */
  6116. EXEC @retcode = dbo.sp_MSreplcheck_publish
  6117. IF @@ERROR <> 0 or @retcode <> 0
  6118.     return (1)
  6119.  
  6120. select @db_name=db_name()
  6121. select @pubid = newid()
  6122. select @objid = 0
  6123.  
  6124. if (@publication is NULL and @tablename is NULL) or 
  6125.      (@publication is not NULL and @tablename is not NULL)
  6126. begin
  6127.     raiserror('internal error on nullibility', 16, -1)
  6128.     return (1)
  6129. end
  6130.  
  6131. if @tablename is not NULL
  6132. begin
  6133.     select @tablelevel = 1
  6134.     select @objid = id from sysobjects where name=@tablename
  6135. end
  6136. else
  6137. begin
  6138.     select @tablelevel = 0
  6139.     select @pubid = pubid from sysmergepublications 
  6140.         where name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=@db_name
  6141. end
  6142.  
  6143. if exists (select * from sysmergearticles where identity_support<>0 and 
  6144.     ((pubid=@pubid and @tablelevel=0) or (@tablelevel=1 and objid=@objid)))
  6145. begin    
  6146.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  6147.         IF @@ERROR <> 0 or @retcode <> 0
  6148.             return (1)
  6149.  
  6150.     declare one_article CURSOR LOCAL FAST_FORWARD FOR 
  6151.         select DISTINCT artid from sysmergearticles where identity_support<>0 and
  6152.             ((pubid=@pubid and @tablelevel=0) or (@tablelevel=1 and objid=@objid))
  6153.     open one_article
  6154.     fetch one_article into @artid
  6155.     while (@@fetch_status<>-1)
  6156.     begin
  6157.         select @objid=objid, @identity_support=identity_support from sysmergearticles 
  6158.                 where pubid=@pubid and artid=@artid
  6159.         select @tablename=object_name(@objid)
  6160.         select @user_name=user_name(uid) from sysobjects where id=@objid
  6161.         select @qualname=QUOTENAME(@user_name) + '.' + QUOTENAME(@tablename)
  6162.         select @next_seed=NULL, @range=NULL, @threshold=NULL --null if not being updated later
  6163.  
  6164.         select @current_max=0, @next_seed=0, @threshold=0, @range=0, @pub_range=0  --make them non-NULL
  6165.         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  6166.         exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  6167.                                       @publisher_db=@db_name,
  6168.                                       @tablename=@tablename,
  6169.                                       @range=@range OUTPUT,
  6170.                                       @current_max=@current_max OUTPUT,
  6171.                                       @threshold=@threshold OUTPUT,
  6172.                                       @next_seed = @next_seed OUTPUT,
  6173.                                       @pub_range=@pub_range OUTPUT
  6174.         if @retcode<>0 or @@ERROR<>0
  6175.             return (1)
  6176.  
  6177.         select @identity_so_far = IDENT_CURRENT(@tablename)
  6178.         select @flag=1
  6179.         if ident_incr(@tablename) < 0
  6180.             select @flag = -1
  6181.  
  6182.         /* To avoid div by zero errors, error out if pub_range is 0 */
  6183.         if @pub_range = 0
  6184.             begin
  6185.                 return 1
  6186.             end
  6187.     
  6188.         if @flag * 100 * (@identity_so_far - (@current_max + 1 - @pub_range))/@pub_range > @threshold
  6189.         begin
  6190.             select @c_max=@next_seed + @pub_range - 1
  6191.             select @n_seed=@next_seed + @pub_range
  6192.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadjust_pub_identity'
  6193.             exec  @retcode=@distproc @publisher=@@SERVERNAME,
  6194.                                     @publisher_db=@db_name,
  6195.                                     @tablename=@tablename,
  6196.                                     @current_max=@c_max,
  6197.                                     @next_seed = @n_seed
  6198.             if @retcode<>0 or @@ERROR<>0
  6199.                 return (1)
  6200.             exec @retcode=sp_MSreseed @objid, @next_seed, @pub_range, 1
  6201.             if @@ERROR <> 0 or @retcode<>0
  6202.                 begin
  6203.                     raiserror(21197, 16, -1)
  6204.                     return (1)
  6205.                 end
  6206.             select @next_seed=@next_seed + @pub_range
  6207.         end
  6208.     fetch next from one_article into @artid
  6209.     end
  6210. end
  6211. else
  6212. begin
  6213.     raiserror(21295, 16, -1, @publication)
  6214.     return (1)
  6215. end
  6216. GO
  6217. exec dbo.sp_MS_marksystemobject sp_MSadjustmergeidentity 
  6218. go
  6219. grant exec on sp_MSadjustmergeidentity to public
  6220. go
  6221.  
  6222. /*
  6223. ** This SP is called to see if merge publication is still allowed for current database.
  6224. ** Merge publishing is disallowed if current DB subscribes as local/anonymous subscriber
  6225. ** 1 means OK, 0 for publication not allowed.
  6226. */
  6227. raiserror('Creating procedure sp_helpallowmerge_publication', 0,1)
  6228. GO
  6229.  
  6230. CREATE PROCEDURE sp_helpallowmerge_publication 
  6231. AS
  6232. declare @srvid      int
  6233. declare @db_name    sysname
  6234.  
  6235. /* Select srvid = 0 for the local server name */
  6236. select @srvid = 0
  6237. select @db_name = db_name()
  6238. if exists (select name from sysobjects where name='sysmergesubscriptions')
  6239.     if exists (select priority from sysmergesubscriptions where db_name=@db_name and srvid = @srvid and priority=0)
  6240.         begin
  6241.             select 0
  6242.             RETURN (0)
  6243.         end
  6244. select 1
  6245. GO
  6246. exec dbo.sp_MS_marksystemobject sp_helpallowmerge_publication 
  6247. go
  6248.  
  6249. raiserror('Creating procedure sp_helpmergearticle', 0,1)
  6250. GO
  6251.  
  6252. CREATE PROCEDURE sp_helpmergearticle (
  6253.     @publication sysname = '%',   /* The publication name */
  6254.     @article sysname = '%'        /* The article name */
  6255.     ) AS
  6256.  
  6257.     SET NOCOUNT ON
  6258.  
  6259.     /*
  6260.     ** Declarations.
  6261.     */
  6262.     declare @retcode            int
  6263.     /*
  6264.     ** Create a temporary table to hold all information.
  6265.     */
  6266.     declare @helpmergearticle TABLE
  6267.         (
  6268.             id                      int             identity NOT NULL,
  6269.             name                    sysname         collate database_default not null,
  6270.             source_owner            sysname         collate database_default not null,
  6271.             source_object           sysname         collate database_default not null,      /* converted from objid */
  6272.             sync_object_owner       sysname         collate database_default null,
  6273.             sync_object             sysname         collate database_default null,      /* converted from sync_objid */
  6274.             description             nvarchar(255)   collate database_default null,
  6275.             status                  tinyint         NULL,
  6276.             creation_script         nvarchar(255)   collate database_default null,
  6277.             conflict_table          nvarchar(270)   collate database_default null,
  6278.             article_resolver        nvarchar(255)   collate database_default null,
  6279.             subset_filterclause     nvarchar(1000)  collate database_default null,
  6280.             pre_creation_command    tinyint         NULL, 
  6281.             schema_option           binary(8)       NULL,
  6282.             type                    smallint        NULL,
  6283.             column_tracking         int             NULL,
  6284.             resolver_info           nvarchar(255)   collate database_default null,
  6285.             vertical_partition        bit                NULL,
  6286.             destination_owner        sysname            collate database_default null,
  6287.             identity_support        int                NULL,
  6288.             pub_identity_range        bigint            NULL,
  6289.             identity_range            bigint            NULL,
  6290.             threshold                int                NULL,
  6291.             verify_resolver_signature int            NULL,
  6292.             destination_object      sysname         collate database_default not null,
  6293.             allow_interactive_resolver    int            NULL,
  6294.             fast_multicol_updateproc    int            NULL,
  6295.             check_permissions        int                NULL                    
  6296.         )
  6297.         
  6298.     /*
  6299.     ** Running sp_help is OK from everywhere, whether enabled for publishing or not
  6300.     */
  6301.     IF not exists (select * from sysobjects where name= 'sysmergesubscriptions')
  6302.         RETURN (0)
  6303.  
  6304.     /*
  6305.     ** Security Check. To public.
  6306.     */
  6307.     
  6308.  
  6309.     /*
  6310.     ** Parameter Check:  @publication.
  6311.     ** Check to make sure that the publication exists, that it conforms
  6312.     ** to the rules for identifiers, and that it isn't NULL.
  6313.     */
  6314.  
  6315.     if @publication IS NULL
  6316.         BEGIN
  6317.             RAISERROR (14043, 16, -1, '@publication')
  6318.             RETURN (1)
  6319.         END
  6320.  
  6321.        if @publication <> '%'
  6322.         BEGIN
  6323.             if NOT EXISTS (select pubid 
  6324.                                 FROM sysmergepublications
  6325.                                 WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
  6326.                 BEGIN
  6327.                     RAISERROR (20026, 16, -1, @publication)
  6328.                     RETURN (1)
  6329.                 END
  6330.  
  6331.         END
  6332.  
  6333.     /*
  6334.     ** Parameter Check:  @article.
  6335.     ** Check to make sure that the article exists, that it conforms
  6336.     ** to the rules for identifiers, and that it isn't NULL.
  6337.     */
  6338.  
  6339.     if @article IS NULL
  6340.         BEGIN
  6341.             RAISERROR (14043, 16, -1, '@article')
  6342.             RETURN (1)
  6343.         END
  6344.  
  6345.     if @article <> '%'
  6346.         BEGIN
  6347.             if NOT EXISTS (select *
  6348.                            FROM sysmergeextendedarticlesview
  6349.                            WHERE name = @article
  6350.                            AND pubid IN (select pubid 
  6351.                                          FROM sysmergepublications 
  6352.                                          WHERE name like @publication  
  6353.                                             and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()))
  6354.                 BEGIN
  6355.                     RAISERROR (20027, 16, -1, @article)
  6356.                     RETURN (1)
  6357.                 END
  6358.  
  6359.         END
  6360.  
  6361.     
  6362.     INSERT INTO @helpmergearticle 
  6363.         (name, 
  6364.         source_owner,
  6365.         source_object, 
  6366.         sync_object_owner,
  6367.         sync_object, 
  6368.         description, 
  6369.         status, 
  6370.         creation_script, 
  6371.         conflict_table, 
  6372.         pre_creation_command, 
  6373.         schema_option, 
  6374.         type, 
  6375.         column_tracking, 
  6376.         article_resolver, 
  6377.         subset_filterclause,
  6378.         resolver_info,
  6379.         vertical_partition,
  6380.         destination_owner,
  6381.         identity_support,
  6382.         pub_identity_range,
  6383.         identity_range,
  6384.         threshold,
  6385.         verify_resolver_signature,
  6386.         destination_object,
  6387.         allow_interactive_resolver,
  6388.         fast_multicol_updateproc,
  6389.         check_permissions)(
  6390.     select  art.name,
  6391.             users1.name,
  6392.             objects.name, 
  6393.             users2.name,
  6394.             syncobjects.name, 
  6395.             art.description, 
  6396.             art.status, 
  6397.             art.creation_script, 
  6398.             art.conflict_table, 
  6399.             art.pre_creation_command,
  6400.             art.schema_option, 
  6401.             case 
  6402.                 when objectproperty(art.objid, 'IsSchemaBound') = 1 and art.type <> 0x80 then 0x0100 | convert(smallint, art.type) 
  6403.                 else convert(smallint, ISNULL(art.type,0x0a)) 
  6404.                 end,
  6405.             art.column_tracking, 
  6406.             art.article_resolver, 
  6407.             art.subset_filterclause,
  6408.             art.resolver_info,
  6409.             art.vertical_partition,
  6410.             art.destination_owner,
  6411.             art.identity_support,
  6412.             ABS(ir.pub_range),
  6413.             ABS(ir.range),
  6414.             ir.threshold,
  6415.             art.verify_resolver_signature,
  6416.             art.destination_object,
  6417.             art.allow_interactive_resolver,
  6418.             art.fast_multicol_updateproc,
  6419.             art.check_permissions
  6420.     FROM    sysmergeextendedarticlesview art left outer join MSrepl_identity_range ir on art.objid=ir.objid 
  6421.             inner join sysmergepublications pubs on art.pubid = pubs.pubid
  6422.             inner join sysobjects objects on objects.id = art.objid
  6423.             left outer join sysobjects syncobjects on art.sync_objid = syncobjects.id 
  6424.             inner join sysusers users1 on objects.uid = users1.uid
  6425.             left outer join sysusers users2 on syncobjects.uid = users2.uid
  6426.             WHERE art.name LIKE @article
  6427.                 AND pubs.name LIKE @publication
  6428.                 AND UPPER(pubs.publisher) = UPPER(@@servername)
  6429.                 AND pubs.publisher_db = db_name())
  6430.             order by art.nickname desc
  6431.  
  6432.     select * from @helpmergearticle 
  6433.     RETURN (0)
  6434. go
  6435. exec dbo.sp_MS_marksystemobject sp_helpmergearticle 
  6436. go
  6437.  
  6438. grant execute on dbo.sp_helpmergearticle to public
  6439. go
  6440.  
  6441. raiserror('Creating procedure sp_dropmergearticle', 0,1)
  6442. GO
  6443.  
  6444. CREATE PROCEDURE sp_dropmergearticle(
  6445.     @publication sysname,     /* The publication name */
  6446.     @article sysname,         /* The article name */
  6447.     @ignore_distributor bit = 0,
  6448.     @reserved bit = 0,
  6449.     @force_invalidate_snapshot bit = 0
  6450.     ) AS
  6451.  
  6452.     set nocount on
  6453.     /*
  6454.     ** Declarations.
  6455.     */
  6456.  
  6457.     declare @db_name                sysname
  6458.     declare @cmd                    nvarchar(255)
  6459.     declare @artid                  uniqueidentifier
  6460.     declare @snapshot_ready            int
  6461.     declare @objid                  int
  6462.     declare @pubid                  uniqueidentifier
  6463.     declare @pubidstr               nvarchar(38)
  6464.     declare @merge_pub_object_bit   int
  6465.     declare @unpublish_bit          int
  6466.     declare @retcode                int
  6467.     declare @replinfo               int
  6468.     declare @dbname                 sysname
  6469.     declare @distributor            sysname
  6470.     declare @distribdb              sysname
  6471.     declare @distproc               nvarchar(300)
  6472.     declare @object_name            sysname
  6473.     declare @uid                    smallint
  6474.     declare @owner                  sysname
  6475.     declare @qualified_name         nvarchar(270)
  6476.     declare @filterid                int
  6477.     declare @proc_name                sysname
  6478.     declare @implicit_transaction    int
  6479.     declare @close_cursor_at_commit int
  6480.     declare @sync_objid     int
  6481.     declare @view_type        int
  6482.     declare @type           tinyint
  6483.     declare @allow_anonymous    int
  6484.     select @close_cursor_at_commit = 0
  6485.     select @implicit_transaction = 0
  6486.     /*
  6487.     ** Save setting values first before changing them
  6488.     */
  6489.     IF (@reserved = 0)
  6490.     BEGIN
  6491.         SELECT @implicit_transaction = @@options & 2
  6492.         SELECT @close_cursor_at_commit = @@options & 4
  6493.         SET IMPLICIT_TRANSACTIONS OFF
  6494.         SET CURSOR_CLOSE_ON_COMMIT OFF
  6495.     END
  6496.     
  6497.     /*
  6498.     ** Initializations.
  6499.     */
  6500.     -- merge uses bit 8 in replinfo
  6501.     select @merge_pub_object_bit    = 128  
  6502.     select @unpublish_bit = ~@merge_pub_object_bit
  6503.  
  6504.  
  6505.     /*
  6506.     ** Security Check
  6507.     */
  6508.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  6509.     IF @@ERROR <> 0 or @retcode <> 0
  6510.         return (1)
  6511.  
  6512.     /* make sure current database is enabled for merge replication */
  6513.     exec @retcode=dbo.sp_MSCheckmergereplication
  6514.     if @@ERROR<>0 or @retcode<>0
  6515.         return (1)
  6516.         
  6517.     select @pubid = pubid, @snapshot_ready=snapshot_ready, @allow_anonymous=allow_anonymous FROM sysmergepublications 
  6518.         WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  6519.     if @pubid is NULL
  6520.         BEGIN
  6521.             RAISERROR (20026, 16, -1, @publication)
  6522.             RETURN (1)
  6523.         END
  6524.  
  6525.     /*
  6526.     ** Once snapshot is ready, do not allow dropping an article except
  6527.     ** when the article is schema-only.
  6528.     */
  6529.     if @snapshot_ready>0 and 
  6530.        (@allow_anonymous=1 or 
  6531.        exists (select * from sysmergesubscriptions 
  6532.                 where pubid=@pubid and subid<>pubid and status=1)) and
  6533.        not exists (select * from sysmergeschemaarticles 
  6534.                     where pubid = @pubid and name = @article)  
  6535.         begin
  6536.             RAISERROR (21338, 16, -1, @article, @publication)
  6537.             RETURN (1)
  6538.         end
  6539.  
  6540.     if @snapshot_ready>0
  6541.         begin
  6542.             if @force_invalidate_snapshot = 0
  6543.                 begin
  6544.                     raiserror(21379, 16, -1, @article, @publication)
  6545.                     return (1)
  6546.                 end
  6547.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  6548.             if @@ERROR<>0
  6549.                 return (1)
  6550.         end
  6551.     
  6552.     
  6553.     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  6554.  
  6555.     /*
  6556.     ** Parameter Check:  @article.
  6557.     ** If the @article is 'all', drop all articles for the specified
  6558.     ** publication (@publication).
  6559.     */
  6560.  
  6561.     if LOWER(@article) = 'all'
  6562.         BEGIN
  6563.             declare hC CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergeextendedarticlesview WHERE pubid=@pubid FOR READ ONLY
  6564.             
  6565.             OPEN hC
  6566.             FETCH hC INTO @article
  6567.             WHILE (@@fetch_status <> -1)
  6568.                 BEGIN
  6569.                     EXECUTE dbo.sp_dropmergearticle @publication, @article,
  6570.                         @ignore_distributor = @ignore_distributor,
  6571.                         @reserved = 1
  6572.                     FETCH hC INTO @article
  6573.                 END
  6574.             CLOSE hC
  6575.             DEALLOCATE hC
  6576.             RETURN (0)
  6577.         END
  6578.  
  6579.     /*
  6580.     ** Parameter Check: @article.
  6581.     ** The @article name must conform to the rules for identifiers.
  6582.     */
  6583.  
  6584.     if @article IS NULL
  6585.         BEGIN
  6586.             RAISERROR (14043, 16, -1, '@article')
  6587.             RETURN (1)
  6588.         END
  6589.  
  6590.     /*
  6591.     ** Parameter Check: @publication.
  6592.     ** The @publication name must conform to the rules for identifiers.
  6593.     */
  6594.  
  6595.     if @publication IS NULL
  6596.         BEGIN
  6597.             RAISERROR (14043, 16, -1, '@publication')
  6598.             RETURN (1)
  6599.         END
  6600.  
  6601.     /*
  6602.     ** Ascertain the existence of the article.
  6603.     */
  6604.     select @type = NULL
  6605.     select @type = type ,
  6606.            @artid = artid
  6607.       from sysmergeextendedarticlesview 
  6608.      where name = @article
  6609.        and pubid = @pubid
  6610.  
  6611.     if @type is NULL
  6612.         begin
  6613.             raiserror (20027, 16, -1, @article)
  6614.             return (1)
  6615.         end
  6616.  
  6617.     -- if all articles are to be dropped, ignore this checking.
  6618.     if @reserved=0 and exists (select * from sysmergesubsetfilters where pubid=@pubid and join_articlename=@article)
  6619.         begin
  6620.             raiserror(21421, 16, -1, @article)
  6621.             return (1)
  6622.         end
  6623.  
  6624.     /*
  6625.     **  Delete article from sysmergearticles and clear publish bit in
  6626.     **  sysobjects.
  6627.     */
  6628.  
  6629.     begin tran 
  6630.     save TRAN dropmergearticle
  6631.         /*
  6632.         ** Remove the corresponding rows from sysmergeschemachange
  6633.         */
  6634.         DELETE FROM sysmergeschemachange WHERE artid = @artid AND pubid = @pubid
  6635.         if @@ERROR <> 0
  6636.             goto FAILURE
  6637.         /*
  6638.         ** Removing a schema only article is a lot simpler than 
  6639.         ** removing a table article so a different code path is created
  6640.         ** to handle this.  
  6641.         */
  6642.         if @type in (0x20, 0x40, 0x80)
  6643.             begin
  6644.             /*
  6645.             ** Retrieve the object id of the underlying proc or view object.
  6646.             */
  6647.             select @objid = objid
  6648.                 from sysmergeschemaarticles where name = @article and pubid = @pubid
  6649.                 
  6650.             /*
  6651.             ** Remove the corresponding record in sysmergeschemaarticles
  6652.             */
  6653.             delete sysmergeschemaarticles where name = @article and pubid = @pubid
  6654.  
  6655.             /*
  6656.             ** If this is the last schema only article for the underlying 
  6657.             ** view or proc object, unmark the 0x200 bit in sysobject.replinfo  
  6658.             */
  6659.             if not exists (select * from sysmergeschemaarticles 
  6660.                             where objid = @objid)
  6661.                 begin
  6662.                 select @merge_pub_object_bit = 512
  6663.                 select @unpublish_bit = ~(@merge_pub_object_bit)
  6664.                 if not exists (select * from sysobjects 
  6665.                                 where name = 'sysschemaarticles')
  6666.                     begin   
  6667.                     update sysobjects set replinfo = (@unpublish_bit & replinfo) where id = @objid
  6668.                     end    
  6669.                 else if  not exists (select * from sysschemaarticles 
  6670.                                       where objid = @objid) 
  6671.                     begin   
  6672.                     update sysobjects set replinfo = (@unpublish_bit & replinfo) where id = @objid
  6673.                     end    
  6674.                 end
  6675.             end
  6676.         else 
  6677.             begin
  6678.             /*
  6679.             ** Retrieve the object id of the underlying table.
  6680.             */
  6681.             select @sync_objid = sync_objid, @view_type = view_type, @artid = artid, @objid = objid
  6682.                 from sysmergearticles where name = @article AND pubid = @pubid
  6683.             select @replinfo = replinfo, @object_name=name, @owner= user_name(uid) from sysobjects where id = @objid
  6684.         
  6685.             /*
  6686.             ** If this is the last article that refers to the base table, drop the 
  6687.             ** triggers and stored procs 
  6688.             */
  6689.             if NOT exists (select * from sysmergearticles WHERE artid = @artid AND pubid <> @pubid)
  6690.                 begin
  6691.                 /*
  6692.                 ** Cleanup the triggers and stored procs
  6693.                 */
  6694.                 EXECUTE @retcode = dbo.sp_MSarticlecleanup @artid = @artid, @pubid = @pubid
  6695.                 if @@ERROR <> 0 OR @retcode <> 0
  6696.                     BEGIN
  6697.                         GOTO FAILURE
  6698.                     END
  6699.             
  6700.                 /*
  6701.                 ** Clear the replication bit in sysobjects. Now merge and transactional level
  6702.                 ** uses different replication bit, checking transactional level is not needed.
  6703.                 */
  6704.  
  6705.                 select @qualified_name = (QUOTENAME(@owner) + '.' + QUOTENAME(@object_name))
  6706.                 exec @retcode = dbo.sp_replupdateschema @qualified_name
  6707.                 if @@ERROR <> 0 OR @retcode <> 0
  6708.                     BEGIN
  6709.                         GOTO FAILURE
  6710.                     END
  6711.             
  6712.                 update sysobjects set replinfo = (replinfo & @unpublish_bit) where id = @objid
  6713.  
  6714.                 IF @@ERROR <> 0
  6715.                     goto FAILURE
  6716.                 end             
  6717.             else
  6718.                 begin
  6719.                 /* Always drop the article proc's they are not shared among publications */
  6720.                 EXECUTE @retcode = dbo.sp_MSdroparticleprocs @artid = @artid, @pubid = @pubid
  6721.                 if @@ERROR <> 0 OR @retcode <> 0
  6722.                     begin
  6723.                         goto FAILURE
  6724.                     end
  6725.                 /* If the article's has a temporary ( view type = 2) or a permanent view (view_type = 1 ) drop the sync object */
  6726.                 if (@view_type = 1 OR @view_type = 2)
  6727.                     begin
  6728.                     declare @viewname sysname
  6729.                     select @viewname = sysobjects.name from sysobjects where 
  6730.                         ObjectProperty (sysobjects.id, 'IsView') = 1 
  6731.                         and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 
  6732.                         and sysobjects.id = @sync_objid
  6733.                     if @viewname IS NOT NULL
  6734.                         begin
  6735.                             set @viewname = QUOTENAME(@viewname)
  6736.                             exec ('drop view ' + @viewname)
  6737.                             if @@ERROR<>0  GOTO FAILURE
  6738.                         end
  6739.                     end
  6740.                 end
  6741.             /*
  6742.             ** Remove the row from sysmergearticles.
  6743.             */
  6744.             DELETE FROM sysmergearticles WHERE artid = @artid AND pubid = @pubid
  6745.             if @@ERROR <> 0
  6746.                 BEGIN
  6747.                     GOTO FAILURE
  6748.                 END
  6749.  
  6750.  
  6751.             /* delete all the filter components that are defined upon the designated article */
  6752.             select @filterid = min(join_filterid) from sysmergesubsetfilters where
  6753.                 artid = @artid AND pubid = @pubid
  6754.             while (@filterid is not null)
  6755.                 begin
  6756.                 select @proc_name = expand_proc from sysmergesubsetfilters where
  6757.                     artid = @artid AND pubid = @pubid and join_filterid = @filterid
  6758.  
  6759.                 if (@proc_name IS NOT NULL) and exists (select * from sysobjects where
  6760.                     name = @proc_name and type = 'P')
  6761.                     begin
  6762.                         exec ('drop proc ' + @proc_name)
  6763.                         IF @@ERROR <> 0
  6764.                         goto FAILURE
  6765.                     end
  6766.                 delete from sysmergesubsetfilters where
  6767.                     artid = @artid AND pubid = @pubid and join_filterid = @filterid
  6768.                 IF @@ERROR <> 0
  6769.                        goto FAILURE
  6770.                 select @filterid = min(join_filterid) from sysmergesubsetfilters where
  6771.                     artid = @artid AND pubid = @pubid
  6772.                 end
  6773.  
  6774.  
  6775.             /*
  6776.             ** set the pub type to subset or full as appropriate
  6777.             */
  6778.             execute @retcode = dbo.sp_MSsubsetpublication @publication
  6779.             if @@ERROR <> 0 or @retcode <> 0 
  6780.                 RETURN (1)
  6781.                 
  6782.             /*
  6783.             ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  6784.             */
  6785.             if @ignore_distributor = 0
  6786.                 begin
  6787.                 /*
  6788.                 ** Get distribution server information for remote RPC call.
  6789.                 */
  6790.                 EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  6791.                    @distribdb   = @distribdb OUTPUT
  6792.                 IF @@ERROR <> 0 or @retcode <> 0
  6793.                     BEGIN
  6794.                         goto FAILURE
  6795.                     END
  6796.  
  6797.                 SELECT @dbname =  DB_NAME()
  6798.         
  6799.                 SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  6800.                     '.dbo.sp_MSdrop_article'
  6801.                 EXECUTE @retcode = @distproc
  6802.                     @publisher = @@SERVERNAME,
  6803.                     @publisher_db = @dbname,
  6804.                     @publication = @publication,
  6805.                     @article = @article
  6806.                       
  6807.                 IF @@ERROR <> 0 or @retcode <> 0
  6808.                     BEGIN
  6809.                         goto FAILURE
  6810.                     END
  6811.                 end
  6812.             end            
  6813.     
  6814.     COMMIT TRAN
  6815.     /*
  6816.     ** Set back original settings
  6817.     */    
  6818.     IF @reserved = 0
  6819.     BEGIN
  6820.         IF @implicit_transaction <>0 
  6821.             SET IMPLICIT_TRANSACTIONS ON
  6822.         IF @close_cursor_at_commit <>0 
  6823.             SET CURSOR_CLOSE_ON_COMMIT ON
  6824.     END
  6825.     RETURN (0)
  6826. FAILURE:
  6827.     RAISERROR (14047, 16, -1, @article)
  6828.     if @@TRANCOUNT > 0
  6829.     begin
  6830.         ROLLBACK TRANSACTION dropmergearticle
  6831.         COMMIT TRANSACTION
  6832.     end
  6833.     /*
  6834.     ** Set back original settings
  6835.     */    
  6836.     IF @reserved = 0
  6837.     BEGIN
  6838.         IF @implicit_transaction <>0 
  6839.             SET IMPLICIT_TRANSACTIONS ON
  6840.         IF @close_cursor_at_commit <>0 
  6841.             SET CURSOR_CLOSE_ON_COMMIT ON
  6842.     END
  6843.     RETURN (1)
  6844. go
  6845. exec dbo.sp_MS_marksystemobject sp_dropmergearticle
  6846. go
  6847.  
  6848. grant execute on dbo.sp_dropmergearticle to public
  6849. go
  6850.  
  6851.  
  6852. raiserror('Creating procedure sp_addmergepublication', 0,1)
  6853. GO
  6854.  
  6855. create procedure sp_addmergepublication (
  6856.     @publication            sysname,                /* Publication name */
  6857.     @description            nvarchar(255)= NULL,            /* Publication description */
  6858.     @retention              int         = 14,           /* Retention period of 14 days */
  6859.     @sync_mode              nvarchar(10) = 'native',    /* (bcp)native, (bcp)character */
  6860.     @allow_push             nvarchar(5)  = 'true',      /* Pulication allows push subscriptions */
  6861.     @allow_pull             nvarchar(5)  = 'true',      /* Pulication allows pull subscriptions*/
  6862.     @allow_anonymous        nvarchar(5)  = 'false',     /* Pulication allows anonymous subscriptions */
  6863.     @enabled_for_internet   nvarchar(5)     = 'false',  /* Pulication is enabled for internet */
  6864.     @centralized_conflicts  nvarchar(5)  = 'true',      /* Conflict records stored at publisher : true or false */
  6865.     @dynamic_filters        nvarchar(5) = 'false',      /* Will publication be filtered on dynamic clause? */
  6866.     @snapshot_in_defaultfolder      nvarchar(5) = 'true',       /* Will keep a copy of the snapshot files to the default location if an alternate folder is specified */
  6867.     @alt_snapshot_folder    nvarchar(255) = NULL,       /* Alternate folder for putting the snapshot file for this publication */
  6868.     @pre_snapshot_script    nvarchar(255) = NULL,        /* Pre snapshot commands */
  6869.     @post_snapshot_script   nvarchar(255) = NULL,        /* Post snapshot commands */
  6870.     @compress_snapshot      nvarchar(5) = 'false',        /* Snapshot compression */
  6871.     @ftp_address            sysname = NULL,                /* Post 7.0 FTP Properties */
  6872.     @ftp_port               int = 21,                    /* Post 7.0 FTP Properties */
  6873.     @ftp_subdirectory       nvarchar(255) = NULL,        /* Post 7.0 FTP Properties */
  6874.     @ftp_login              sysname = N'anonymous',        /* Post 7.0 FTP Properties */
  6875.     @ftp_password           sysname = NULL,                /* Post 7.0 FTP Properties */
  6876.     @conflict_retention        int = 14,                    /* Conflict retention period */
  6877.     @keep_partition_changes nvarchar(5) = 'false',        /* Optimized Partition Updates/Deletes */
  6878.     @allow_subscription_copy    nvarchar(5) = 'false',    /* Allow the subscription to be copied */
  6879.     @allow_synctoalternate        nvarchar(5) = 'false',    /* Allow the subscription to be synchronize to alternate partners */
  6880.     @validate_subscriber_info    nvarchar(500) = NULL,    /* Should we validate that subscriber is using right params? */
  6881.     @add_to_active_directory    nvarchar(5) = 'false',
  6882.     @max_concurrent_merge    int = 0,                     /* value of 0 means no such limit exists */
  6883.     @max_concurrent_dynamic_snapshots int = 0           /* Maximum number of concurrent dynamic snapshot sessions */
  6884.     ) as
  6885.  
  6886.     set nocount on
  6887.  
  6888.     /*
  6889.     ** Declarations.
  6890.     */
  6891.     
  6892.     declare @retcode                    int         /* return code value for procedure execution */
  6893.     declare @push                       tinyint     /* subscription type is push */
  6894.     declare @statid                     tinyint     /* status id based on @status */
  6895.     declare @sync_modeid                tinyint     /* sync mode id based on @sync_mode */
  6896.     declare @global                     tinyint     /* subscriber type of loop-back subscription */
  6897.     declare @db_name                    sysname     /* database name */
  6898.     declare @srvid                      int         /* Server ID */
  6899.     declare @nickname                   int         /* replica nickname */
  6900.     declare @tranpublish_bit            smallint    /* online publish bit (flag) in sysdatabases */
  6901.     declare @mergepublish_bit           smallint    /* merge publish bit (flag) in sysdatabases */
  6902.     declare @found                      int         /* flag indicating if publication is found */
  6903.     declare @pubid                      uniqueidentifier    /* Publication identifier */
  6904.     declare @allow_push_id              bit
  6905.     declare @allow_pull_id              bit
  6906.     declare @allow_anonymous_id         bit
  6907.     declare @dynamic_filters_id         bit         
  6908.     declare @allow_subscription_copy_id bit         
  6909.     declare @allow_synctoalternate_id     bit         
  6910.     declare @enabled_for_internet_id    bit
  6911.     declare @centralized_conflicts_id   bit
  6912.     declare @priority                   real        
  6913.     declare @automatic                  tinyint     
  6914.     declare @false                      bit
  6915.     declare @true                       bit
  6916.     declare @distributor                sysname
  6917.     declare @distproc                   nvarchar(300)
  6918.     declare @distribdb                  sysname
  6919.     declare @distpubid                  int
  6920.     declare @full                       int
  6921.     declare @snapshot_in_defaultfolder_bit      bit
  6922.     declare @compress_snapshot_bit      bit
  6923.     declare @keep_before_values_int           int
  6924.     declare @enc_ftp_password           nvarchar(524)
  6925.     declare @ad_guidname                sysname
  6926.     declare @schemaversion              int 
  6927.     declare @schemaguid                 uniqueidentifier
  6928.     declare @schematype                 int
  6929.     declare @schematext                 nvarchar(2000)
  6930.     declare @artid                        uniqueidentifier
  6931.     declare @distservername                sysname
  6932.     declare @backward_comp_level        int
  6933.     
  6934.     /* make sure current database is enabled for merge replication */
  6935.     exec @retcode=dbo.sp_MSCheckmergereplication
  6936.     if @@ERROR<>0 or @retcode<>0
  6937.         return (1)
  6938.  
  6939.     /*
  6940.     ** Initializations
  6941.     */
  6942.     select @backward_comp_level    = 10 --that of 7.0 RTM
  6943.     
  6944.     select @mergepublish_bit    = 4 
  6945.     select @tranpublish_bit     = 1
  6946.     select @priority            = 100.0
  6947.     select @automatic           = 1     /* Const: synchronization type 'automatic' */
  6948.     select @true                = 1
  6949.     select @false               = 0
  6950.     select @full                = 0     /* Const: publication type 'full' */
  6951.  
  6952.     /*
  6953.     ** Set the status to Active (1)
  6954.     */
  6955.     select @statid      = 1
  6956.     select @global      = 1
  6957.     select @push        = 0
  6958.     select @db_name     = DB_NAME()
  6959.     select @ad_guidname = NULL
  6960.  
  6961.     /*
  6962.     ** Security Check
  6963.     */
  6964.  
  6965.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  6966.     IF @@ERROR <> 0 or @retcode <> 0
  6967.         return (1)
  6968.  
  6969.     /*
  6970.     ** Parameter Check: @publication.
  6971.     ** The @publication name must conform to the rules for identifiers,
  6972.     ** and must not be the keyword 'all'.
  6973.     */
  6974.     if @publication is NULL
  6975.         begin
  6976.             raiserror (14043, 16, -1, '@publication')
  6977.             return (1)
  6978.         end
  6979.  
  6980.     exec @retcode = dbo.sp_MSreplcheck_name @publication
  6981.     if @@ERROR <> 0 or @retcode <> 0
  6982.         return(1)
  6983.        
  6984.     if LOWER (@publication) = 'all'
  6985.         begin
  6986.             raiserror (14034, 16, -1)
  6987.             return (1)
  6988.         end
  6989.         
  6990.     if @max_concurrent_merge<0
  6991.         begin
  6992.             raiserror(21402, 16, -1, '@max_concurrent_merge')
  6993.             return (1)
  6994.         end
  6995.  
  6996.     /*
  6997.     ** Parameter Check: @retention.
  6998.     */
  6999.         
  7000.     if @retention is not NULL and @retention<0 
  7001.         begin
  7002.             raiserror(20050, 16, -1, 0)
  7003.             return(1)
  7004.         end
  7005.  
  7006.     if @retention is NULL
  7007.         select @retention = 0
  7008.  
  7009.     /*
  7010.     ** Parameter Check: @conflict_retention.
  7011.     */
  7012.         
  7013.     if @conflict_retention is not NULL and @conflict_retention<0 
  7014.         begin
  7015.             raiserror(20050, 16, -1, 0)
  7016.             return(1)
  7017.         end
  7018.  
  7019.     /*
  7020.     ** if it is NULL, use the default value of 14 days.
  7021.     */
  7022.     if @conflict_retention is NULL 
  7023.         select @conflict_retention = 14
  7024.  
  7025.     /*
  7026.     ** Parameter Check: @sync_mode.
  7027.     ** Make sure that the sync_mode is one of the following:
  7028.     **
  7029.     **  id  sync_mode
  7030.     **  ==  ==========
  7031.     **   0  (bcp)native
  7032.     **   1  (bcp)character
  7033.     */
  7034.     
  7035.     if LOWER(@sync_mode collate SQL_Latin1_General_CP1_CS_AS)='portable' select @sync_mode='character'
  7036.  
  7037.     if LOWER(@sync_mode collate SQL_Latin1_General_CP1_CS_AS) is NULL OR LOWER(@sync_mode collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('bcp native', 'bcp character', 'native', 'character')
  7038.         begin
  7039.             raiserror (20076, 16, -1)
  7040.             return (1)
  7041.         end
  7042.  
  7043.     if LOWER(@sync_mode collate SQL_Latin1_General_CP1_CS_AS) = 'native' or 
  7044.        LOWER(@sync_mode collate SQL_Latin1_General_CP1_CS_AS)='bcp native' 
  7045.         select @sync_modeid = 0
  7046.     else 
  7047.         select @sync_modeid = 1
  7048.  
  7049.     /*
  7050.     ** Parameter Check:  @allow_push.
  7051.     */
  7052.  
  7053.     if @allow_push IS NULL OR LOWER(@allow_push collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7054.         BEGIN
  7055.             RAISERROR (14148, 16, -1, '@allow_push')
  7056.             RETURN (1)
  7057.         END
  7058.  
  7059.     if LOWER(@allow_push collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7060.         select @allow_push_id = 1
  7061.     else 
  7062.         select @allow_push_id = 0
  7063.  
  7064.     /*
  7065.     ** Parameter Check:  @allow_pull.
  7066.     */
  7067.  
  7068.     if @allow_pull IS NULL OR LOWER(@allow_pull collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7069.         BEGIN
  7070.             RAISERROR (14148, 16, -1, '@allow_pull')
  7071.             RETURN (1)
  7072.         END
  7073.     if LOWER(@allow_pull collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7074.         select @allow_pull_id = 1
  7075.     else 
  7076.         select @allow_pull_id = 0
  7077.  
  7078.     /*
  7079.     ** Parameter Check:  @allow_anonymous.
  7080.     */
  7081.  
  7082.     if @allow_anonymous IS NULL OR LOWER(@allow_anonymous collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7083.         BEGIN
  7084.             RAISERROR (14148, 16, -1, '@allow_anonymous')
  7085.             RETURN (1)
  7086.         END
  7087.     if LOWER(@allow_anonymous collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7088.         select @allow_anonymous_id = 1
  7089.     else 
  7090.         select @allow_anonymous_id = 0
  7091.  
  7092.     /*
  7093.     ** Parameter Check:  @enabled_for_internet.
  7094.     */
  7095.  
  7096.     IF @enabled_for_internet IS NULL OR LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7097.         BEGIN
  7098.             RAISERROR (14148, 16, -1, '@enabled_for_internet')
  7099.             RETURN (1)
  7100.         END
  7101.  
  7102.     IF LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7103.         SELECT @enabled_for_internet_id = 1
  7104.     ELSE 
  7105.         SELECT @enabled_for_internet_id = 0
  7106.  
  7107.     /*
  7108.     ** Parameter Check:  @centralized_conflicts.
  7109.     */
  7110.  
  7111.     if @centralized_conflicts IS NULL OR LOWER(@centralized_conflicts collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7112.         BEGIN
  7113.             RAISERROR (14148, 16, -1, '@centralized_conflicts')
  7114.             RETURN (1)
  7115.         END
  7116.     if LOWER(@centralized_conflicts collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7117.         select @centralized_conflicts_id = 1
  7118.     else 
  7119.         begin
  7120.             raiserror(21349, 10, -1, @publication)
  7121.             select @backward_comp_level = 30    -- that of Sphinx SP2, in which decentrailzed logging will be supported.
  7122.             select @centralized_conflicts_id = 0
  7123.         end
  7124.  
  7125.     /*
  7126.     ** Parameter Check:  @dynamic_filter.
  7127.     */
  7128.  
  7129.     IF @dynamic_filters IS NULL OR LOWER(@dynamic_filters collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7130.         BEGIN
  7131.             RAISERROR (14148, 16, -1, '@dynamic_filters')
  7132.             RETURN (1)
  7133.         END
  7134.  
  7135.     IF LOWER(@dynamic_filters collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7136.         SELECT @dynamic_filters_id = 1
  7137.     ELSE 
  7138.         SELECT @dynamic_filters_id = 0
  7139.  
  7140.     if @validate_subscriber_info is not NULL
  7141.         begin
  7142.             if @dynamic_filters_id = 0
  7143.                 begin
  7144.                     raiserror(21313, 16, -1)
  7145.                     return (1)
  7146.                 end
  7147.             exec ('select ' + @validate_subscriber_info)
  7148.             if @@ERROR<>0
  7149.                 begin
  7150.                     raiserror(21299, 16, -1, @validate_subscriber_info)
  7151.                     return (1)
  7152.                 end
  7153.         end
  7154.  
  7155.     -- Portable snapshot
  7156.     IF @snapshot_in_defaultfolder IS NULL OR LOWER(@snapshot_in_defaultfolder collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7157.     BEGIN
  7158.         RAISERROR (14148, 16, -1, '@snapshot_in_defaultfolder')
  7159.         RETURN (1)
  7160.     END
  7161.     
  7162.     IF LOWER(@snapshot_in_defaultfolder collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  7163.     BEGIN
  7164.         SELECT @snapshot_in_defaultfolder_bit = 1
  7165.     END
  7166.     ELSE
  7167.     BEGIN
  7168.         SELECT @snapshot_in_defaultfolder_bit = 0
  7169.     END
  7170.  
  7171.     -- Pre/Post snapshot commands
  7172.     -- If @sync_method is character mode bcp, this would indicate that
  7173.     -- this publication may support non-SQL Server subscribers. In this 
  7174.     -- case, pre- and post- snapshot commands are not allowed.
  7175.     IF @sync_modeid = 1 AND 
  7176.         ((@pre_snapshot_script IS NOT NULL AND @pre_snapshot_script <> N'' ) OR
  7177.          (@post_snapshot_script IS NOT NULL AND @post_snapshot_script <> N''))
  7178.     BEGIN
  7179.         RAISERROR (21151, 16, -1)
  7180.         RETURN (1)
  7181.     END
  7182.  
  7183.     -- Parameter check - @compress_snapshot
  7184.     -- @compress_snapshot can be 1 if @alt_snapshot_folder is non-null
  7185.     IF @compress_snapshot IS NULL OR LOWER(@compress_snapshot collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7186.     BEGIN
  7187.         RAISERROR (14148, 16, -1, '@compress_snapshot')
  7188.         RETURN (1)
  7189.     END
  7190.     
  7191.     IF LOWER(@compress_snapshot collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  7192.     BEGIN
  7193.         SELECT @compress_snapshot_bit = 1
  7194.     END
  7195.     ELSE
  7196.     BEGIN
  7197.         SELECT @compress_snapshot_bit = 0
  7198.     END
  7199.  
  7200.  
  7201.     -- Only bump up the compatibility level if only a compressed snapshot
  7202.     -- is generated at the alternate snapshot folder
  7203.     if @snapshot_in_defaultfolder_bit = 0 and
  7204.        @compress_snapshot_bit = 1
  7205.     begin
  7206.         raiserror(21350, 10, -1, @publication)
  7207.         select @backward_comp_level = 40 -- this is supported starting from 7.5
  7208.     end
  7209.  
  7210.     -- Snapshot compression can only be enabled if an alternate 
  7211.     -- snapshot generation folder exists.
  7212.     IF (@compress_snapshot_bit = 1 AND 
  7213.         (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N''))
  7214.     BEGIN
  7215.         RAISERROR (21157, 16, -1)
  7216.         RETURN (1)
  7217.     END    
  7218.  
  7219.     -- Parameter check: ftp_address
  7220.     -- If the publication is enabled for internet, ftp_address cannot be null
  7221.     IF @enabled_for_internet_id = 1 AND (@ftp_address IS NULL OR @ftp_address = N'')
  7222.     BEGIN
  7223.         RAISERROR (21158, 16, -1)
  7224.         RETURN (1)
  7225.     END     
  7226.  
  7227.  
  7228.     -- Parameter check: enabled_for_internet
  7229.     -- If a publication is enabled for internet, it must have an alternate 
  7230.     -- snapshot folder defined.
  7231.     IF LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) = N'true' AND 
  7232.         (@alt_snapshot_folder = N'' OR
  7233.         (@alt_snapshot_folder IS NULL))
  7234.     BEGIN
  7235.         RAISERROR (21159, 16, -1)
  7236.         RETURN (1)
  7237.     END 
  7238.  
  7239.     -- Parameter check: ftp_port
  7240.     IF @ftp_port IS NULL
  7241.     BEGIN
  7242.         RAISERROR (21160, 16, -1)
  7243.     END
  7244.  
  7245.  
  7246.     -- Encrypt ftp password before putting it into the sysmergepublications
  7247.     -- table if one is provided
  7248.     SELECT @enc_ftp_password = NULL
  7249.     IF @ftp_password IS NOT NULL
  7250.     BEGIN
  7251.         SELECT @enc_ftp_password = @ftp_password 
  7252.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  7253.         IF @retcode <> 0
  7254.         BEGIN
  7255.             RETURN (1)
  7256.         END
  7257.     END    
  7258.  
  7259.     /*
  7260.     ** Parameter Check:  @keep_partition_changes.
  7261.     */
  7262.  
  7263.     if LOWER(@keep_partition_changes collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7264.         BEGIN
  7265.             RAISERROR (14148, 16, -1, '@keep_partition_changes')
  7266.             RETURN (1)
  7267.         END
  7268.  
  7269.     if LOWER(@keep_partition_changes collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7270.         begin
  7271.             set @keep_before_values_int = 1
  7272.         end
  7273.     else 
  7274.         set @keep_before_values_int = 0
  7275.  
  7276.     /*
  7277.     ** Parameter Check:  @allow_subscription_copy_id.
  7278.     */
  7279.  
  7280.     if LOWER(@allow_subscription_copy collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7281.         BEGIN
  7282.             RAISERROR (14148, 16, -1, '@allow_subscription_copy')
  7283.             RETURN (1)
  7284.         END
  7285.         
  7286.     IF LOWER(@allow_subscription_copy collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7287.         SELECT @allow_subscription_copy_id = 1
  7288.     ELSE 
  7289.         SELECT @allow_subscription_copy_id = 0
  7290.  
  7291.     /*
  7292.     ** Parameter Check:  @allow_synctoalternate_id.
  7293.     */
  7294.  
  7295.     if LOWER(@allow_synctoalternate collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7296.         BEGIN
  7297.             RAISERROR (14148, 16, -1, '@allow_synctoalternate')
  7298.             RETURN (1)
  7299.         END
  7300.         
  7301.     IF LOWER(@allow_synctoalternate collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7302.         SELECT @allow_synctoalternate_id = 1
  7303.     ELSE 
  7304.         SELECT @allow_synctoalternate_id = 0
  7305.  
  7306.     /*
  7307.     ** Parameter Check:  @add_to_active_directory.
  7308.     */
  7309.  
  7310.     if LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7311.         BEGIN
  7312.             RAISERROR (14148, 16, -1, '@add_to_active_directory')
  7313.             RETURN (1)
  7314.         END
  7315.  
  7316.    /* Is AD supported? */
  7317.    DECLARE @retval  INT
  7318.    EXECUTE @retval = master.dbo.xp_MSADEnabled
  7319.    if (@retval <> 0) and LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS)='true'
  7320.    begin
  7321.         RAISERROR(21253, 16, -1)
  7322.         RETURN (1)
  7323.    end
  7324.  
  7325.  
  7326.     /*
  7327.     ** Parameter Check: @max_concurrent_dynamic_snapshots
  7328.     */
  7329.     
  7330.     if @max_concurrent_dynamic_snapshots < 0 or @max_concurrent_dynamic_snapshots is null
  7331.     begin
  7332.         raiserror(21403, 16, -1)
  7333.         return (1)
  7334.     end
  7335.         
  7336.     /*
  7337.     ** Check to see if the publication name is already used.
  7338.     ** 1. check merge pubs
  7339.     ** 2. check online publications
  7340.     */
  7341.     if exists (select * from sysmergepublications 
  7342.         where name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
  7343.     begin
  7344.         RAISERROR (20025, 16, -1, @publication)
  7345.         RETURN (1)
  7346.     end
  7347.  
  7348.     if (select category & @tranpublish_bit from master..sysdatabases where name = @db_name collate database_default) <> 0
  7349.     begin
  7350.         EXEC @retcode = dbo.sp_helppublication @publication, @found output
  7351.  
  7352.         if @@ERROR <> 0 OR @retcode <> 0
  7353.         BEGIN
  7354.             RETURN (1)
  7355.         END
  7356.  
  7357.         if @found <> 0 
  7358.         BEGIN
  7359.             RAISERROR (20025, 16, -1, @publication)
  7360.             RETURN (1)
  7361.         END
  7362.     end
  7363.  
  7364.  
  7365.     /*
  7366.     **  Add the publication as the designmaster of the replica set.
  7367.     */
  7368.  
  7369.     /* Generate a guid for the publication ID */
  7370.     set @pubid = newid()
  7371.         
  7372.     /* Select the server's ID as 0 since this is the LOCAL server */
  7373.     select @srvid = 0
  7374.  
  7375.     /* Look for existing nickname from any other subscription */
  7376.     exec @retcode=sp_MSgetreplnick NULL, NULL , NULL,  @nickname out
  7377.     if (@@error <> 0) or @retcode <> 0 
  7378.         begin
  7379.             RETURN(1)
  7380.         end                 
  7381.             
  7382.     /* Generate a new replica nickname from the @pubid */
  7383.     if (@nickname is null)
  7384.     begin
  7385.         execute @retcode = dbo.sp_MSgenreplnickname @pubid, @nickname output
  7386.         IF @@ERROR <>0 OR @retcode <> 0
  7387.         BEGIN
  7388.             RAISERROR (20077, 16, -1)
  7389.             RETURN (1)
  7390.         END
  7391.     end
  7392.     else
  7393.         select @priority=max(priority) from sysmergesubscriptions where db_name=@db_name and srvid = @srvid
  7394.     /*
  7395.     ** A change in design.
  7396.     */
  7397.     if @priority = 0 
  7398.         begin
  7399.             RAISERROR(21087, 16, -1)
  7400.             return (1)
  7401.         end
  7402.  
  7403.     /*
  7404.     ** Get distributor information
  7405.     */
  7406.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUT , @distributor = @distservername  OUTPUT, 
  7407.         @distribdb = @distribdb OUTPUT
  7408.         if @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
  7409.         BEGIN
  7410.             RAISERROR (14071, 16, -1)
  7411.             RETURN (1)
  7412.         END
  7413.     
  7414.     /*
  7415.     **  add an entry into sysmergepublications
  7416.     */
  7417.     begin tran    
  7418.     save tran sp_addmergepublication
  7419.         /* Add row in the publications table */
  7420.         if @backward_comp_level > 10
  7421.         begin
  7422.             exec sp_MSBumpupCompLevel @pubid, @backward_comp_level
  7423.             if @@ERROR<>0
  7424.                 goto FAILURE
  7425.         end
  7426.             
  7427.         insert sysmergepublications
  7428.             (pubid, 
  7429.             name, 
  7430.             description, 
  7431.             designmasterid, 
  7432.             retention, 
  7433.             parentid, 
  7434.             sync_mode, 
  7435.             allow_push, 
  7436.             allow_pull, 
  7437.             allow_anonymous, 
  7438.             centralized_conflicts,
  7439.             status,
  7440.             snapshot_ready,
  7441.             enabled_for_internet,
  7442.             publication_type,
  7443.             dynamic_filters,
  7444.             snapshot_in_defaultfolder,
  7445.             alt_snapshot_folder,
  7446.             pre_snapshot_script,
  7447.             post_snapshot_script,
  7448.             compress_snapshot,
  7449.             ftp_address,
  7450.             ftp_port,
  7451.             ftp_subdirectory,
  7452.             ftp_login,
  7453.             ftp_password,
  7454.             conflict_retention,
  7455.             keep_before_values,
  7456.             allow_subscription_copy,
  7457.             allow_synctoalternate,
  7458.             validate_subscriber_info,
  7459.             ad_guidname,
  7460.             backward_comp_level,
  7461.             max_concurrent_merge,
  7462.             max_concurrent_dynamic_snapshots)
  7463.         values
  7464.             (@pubid, 
  7465.             @publication, 
  7466.             @description, 
  7467.             @pubid, 
  7468.             @retention, 
  7469.             @pubid, 
  7470.             @sync_modeid, 
  7471.             @allow_push_id, 
  7472.             @allow_pull_id, 
  7473.             @allow_anonymous_id, 
  7474.             @centralized_conflicts_id,
  7475.             @statid,
  7476.             @false,
  7477.             @enabled_for_internet_id,
  7478.             @full,
  7479.             @dynamic_filters_id,
  7480.             @snapshot_in_defaultfolder_bit,
  7481.             @alt_snapshot_folder,
  7482.             @pre_snapshot_script,
  7483.             @post_snapshot_script,
  7484.             @compress_snapshot_bit,
  7485.             @ftp_address,
  7486.             @ftp_port,
  7487.             @ftp_subdirectory,
  7488.             @ftp_login,
  7489.             @enc_ftp_password,
  7490.             @conflict_retention,
  7491.             @keep_before_values_int,
  7492.             @allow_subscription_copy_id,
  7493.             @allow_synctoalternate_id,
  7494.             @validate_subscriber_info,
  7495.             @ad_guidname, 
  7496.             @backward_comp_level,
  7497.             @max_concurrent_merge,
  7498.             @max_concurrent_dynamic_snapshots)
  7499.         if @@ERROR <> 0
  7500.             begin
  7501.                 goto FAILURE
  7502.             end
  7503.  
  7504.         /* Add row to represent reciprocal subscription */
  7505.         insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, status, priority, pubid, subscriber_type, subscription_type, sync_type, login_name, subscriber_server, publication, distributor, last_validated)
  7506.             values (@pubid, @pubid, 0, @srvid, @db_name, @statid, @priority, @pubid, @global, @push, @automatic, suser_sname(suser_sid()), @@servername, @publication, @distservername, getdate())
  7507.  
  7508.         if @@ERROR <> 0
  7509.             begin
  7510.                 goto FAILURE
  7511.             end
  7512.         /*
  7513.         **  Add row for merge publication to MSmerge_replinfo.
  7514.         */
  7515.         insert MSmerge_replinfo(repid, replnickname)
  7516.             values (@pubid, @nickname)
  7517.         if @@ERROR <> 0
  7518.             begin
  7519.                 goto FAILURE
  7520.             end
  7521.  
  7522.  
  7523.         /*
  7524.         ** Add the publication to the distributor side
  7525.         */
  7526.         SELECT @distpubid = @nickname
  7527.  
  7528.         select @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  7529.             '.dbo.sp_MSadd_publication'
  7530.         EXECUTE @retcode = @distproc
  7531.             @publisher = @@SERVERNAME,
  7532.             @publisher_db = @db_name,
  7533.             @publication = @publication,
  7534.             --@publication_id = NULL,
  7535.             @publication_type = 2,          -- 0 = Trans, 1 = Snapshot, 2 = Merge
  7536.             @independent_agent = @true,
  7537.             @immediate_sync = @true,
  7538.             @allow_push = @allow_push_id,
  7539.             @allow_pull = @allow_pull_id,
  7540.             @allow_anonymous = @allow_anonymous_id,
  7541.             --@snapshot_agent = NULL,
  7542.             --@logreader_agent = NULL,
  7543.             @description = @description,
  7544.             @retention = @retention,
  7545.             @allow_subscription_copy = @allow_subscription_copy_id
  7546.  
  7547.         IF @@ERROR <> 0 or @retcode <> 0
  7548.             BEGIN
  7549.                 GOTO FAILURE
  7550.             END
  7551.                 
  7552.         -- Populate the initial list.
  7553.         exec @retcode = dbo.sp_grant_publication_access 
  7554.             @publication = @publication,
  7555.             @login = null,
  7556.             @reserved = 'init'
  7557.         IF @@error <> 0 OR @retcode <> 0
  7558.             GOTO FAILURE
  7559.  
  7560.  
  7561.  
  7562.     commit tran
  7563.  
  7564.     --Put this part outside of a TRANSACTION. It can fail without having to affect publication creation.
  7565.     declare @returnstring nvarchar(512) 
  7566.     set @returnstring = N''
  7567.     if LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS)='true'
  7568.     begin
  7569.         --no error checking needed here.    
  7570.  
  7571.         create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  7572.         if @@ERROR<>0
  7573.             goto SKIP_AD
  7574.         insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @db_name
  7575.         if @retcode <> 0 or @@ERROR<>0
  7576.         begin
  7577.             set @returnstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory)
  7578.             goto SKIP_AD           
  7579.         end
  7580.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  7581.         if @ad_guidname is not NULL
  7582.         begin
  7583.             update sysmergepublications set ad_guidname=@ad_guidname where pubid=@pubid
  7584.             if @@ERROR<>0
  7585.                 goto SKIP_AD
  7586.         end
  7587.         drop table #guid_name_for_active_directory
  7588.     end
  7589.     return (0)
  7590. SKIP_AD:
  7591.     drop table #guid_name_for_active_directory
  7592.     if @returnstring is NULL
  7593.         select @returnstring = N''
  7594.     raiserror(21363, 16, -1, @publication, @returnstring)
  7595.     return (1) 
  7596. FAILURE:
  7597.     RAISERROR (14018, 16, -1)
  7598.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  7599.     if @@TRANCOUNT > 0
  7600.     begin
  7601.         ROLLBACK TRANSACTION sp_addmergepublication
  7602.         COMMIT TRANSACTION
  7603.     end
  7604.     return (1)
  7605. go
  7606. exec dbo.sp_MS_marksystemobject sp_addmergepublication 
  7607. go
  7608.  
  7609. grant execute on dbo.sp_addmergepublication to public
  7610. go
  7611.  
  7612. raiserror('Creating procedure sp_changemergepublication', 0,1)
  7613. GO
  7614.  
  7615. CREATE PROCEDURE sp_changemergepublication (
  7616.     @publication sysname,                  /* Publication name */
  7617.     @property sysname = NULL,              /* The property to change */
  7618.     @value nvarchar(255) = NULL,        /* The new property value */
  7619.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  7620.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  7621.     ) AS
  7622.  
  7623.     SET NOCOUNT ON
  7624.  
  7625.     /*
  7626.     ** Declarations.
  7627.     */
  7628.     declare @max_concurrent_merge    int
  7629.     declare @cmd                nvarchar(255)
  7630.     declare @pubid              uniqueidentifier
  7631.     declare @pubidstr           nvarchar(38)
  7632.     declare @retcode            int
  7633.     declare @retention          int
  7634.     declare @statusid           tinyint
  7635.     declare @sync_modeid        tinyint
  7636.     declare @distributor        sysname
  7637.     declare @distproc           nvarchar(300)
  7638.     declare @value_bit          bit
  7639.     declare @snapshot_ready     tinyint
  7640.     declare @subscribed         int
  7641.     declare @dbname             sysname
  7642.     declare @distribdb          sysname
  7643.     declare @alt_snapshot_folder nvarchar(255)
  7644.     declare @enabled_for_internet bit
  7645.     declare @ftp_address        sysname
  7646.     declare @enc_ftp_password   nvarchar(524)
  7647.     declare @snapshot_in_defaultfolder bit
  7648.     declare @dynamic_filters_id    int
  7649.     declare @schemaversion      int 
  7650.     declare @schemaguid         uniqueidentifier
  7651.     declare @schematype         int
  7652.     declare @schematext         nvarchar(2000)
  7653.     declare @artid                uniqueidentifier
  7654.     declare @in_ActiveD            bit
  7655.     declare @ad_guidname        sysname
  7656.     declare @db_name            sysname
  7657.     declare @compress_snapshot  bit
  7658.     declare @numeric_value      int
  7659.  
  7660.     /*
  7661.     ** Initializations
  7662.     */
  7663.     select @subscribed = 1
  7664.     select @snapshot_ready = 1
  7665.     select @db_name=db_name()
  7666.     /*
  7667.     ** Security Check
  7668.     */
  7669.  
  7670.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  7671.     IF @@ERROR <> 0 or @retcode <> 0
  7672.         return (1)
  7673.  
  7674.     /* 
  7675.     ** Check if current DB is enabled for publication/subscription
  7676.     */
  7677.     
  7678.     /* make sure current database is enabled for merge replication */
  7679.     exec @retcode=dbo.sp_MSCheckmergereplication
  7680.     if @@ERROR<>0 or @retcode<>0
  7681.         return (1)
  7682.             
  7683.     /*
  7684.     ** Parameter Check:  @property.
  7685.     ** If the @property parameter is NULL, print the options.
  7686.     */
  7687.     if @property IS NULL
  7688.         BEGIN
  7689.             CREATE TABLE #tab1 (properties sysname collate database_default)
  7690.             INSERT INTO #tab1 VALUES ('description')
  7691.             INSERT INTO #tab1 VALUES ('status')
  7692.             INSERT INTO #tab1 VALUES ('retention')
  7693.             INSERT INTO #tab1 VALUES ('sync_mode')
  7694.             INSERT INTO #tab1 VALUES ('allow_push')
  7695.             INSERT INTO #tab1 VALUES ('allow_pull')
  7696.             INSERT INTO #tab1 VALUES ('allow_anonymous')
  7697.             INSERT INTO #tab1 VALUES ('enabled_for_internet')
  7698.             INSERT INTO #tab1 VALUES ('centralized_conflicts')
  7699.             INSERT INTO #tab1 VALUES ('snapshot_ready')
  7700.             INSERT INTO #tab1 VALUES ('snapshot_in_defaultfolder')
  7701.             INSERT INTO #tab1 VALUES ('alt_snapshot_folder')
  7702.             INSERT INTO #tab1 VALUES ('pre_snapshot_script')
  7703.             INSERT INTO #tab1 VALUES ('post_snapshot_script')
  7704.             INSERT INTO #tab1 VALUES ('compress_snapshot')
  7705.             INSERT INTO #tab1 VALUES ('ftp_address')
  7706.             INSERT INTO #tab1 VALUES ('ftp_port')
  7707.             INSERT INTO #tab1 VALUES ('ftp_subdirectory')
  7708.             INSERT INTO #tab1 VALUES ('ftp_login')
  7709.             INSERT INTO #tab1 VALUES ('ftp_password')
  7710.             INSERT INTO #tab1 VALUES ('conflict_retention')
  7711.             INSERT INTO #tab1 VALUES ('allow_subscription_copy')
  7712.             INSERT INTO #tab1 VALUES ('allow_synctoalternate')
  7713.             INSERT INTO #tab1 VALUES ('validate_subscriber_info')
  7714.             INSERT INTO #tab1 VALUES ('publish_to_ActiveDirectory')
  7715.             INSERT INTO #tab1 VALUES ('dynamic_filters')
  7716.             INSERT INTO #tab1 VALUES ('max_concurrent_merge')
  7717.             INSERT INTO #tab1 VALUES ('max_concurrent_dynamic_snapshots')
  7718.             select * FROM #tab1
  7719.             RETURN (0)
  7720.         END
  7721.  
  7722.     if @value is NULL and LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) not in 
  7723.                                                   ('description', 
  7724.                                                    'alt_snapshot_folder',
  7725.                                                    'pre_snapshot_script',
  7726.                                                    'post_snapshot_script',
  7727.                                                    'ftp_address',
  7728.                                                    'ftp_subdirectory',
  7729.                                                    'ftp_login',
  7730.                                                    'ftp_password',
  7731.                                                    'max_concurrent_merge')
  7732.         begin
  7733.             RAISERROR (20081, 16, -1, @property)
  7734.             RETURN (1)
  7735.         end
  7736.  
  7737.     /*
  7738.     ** Parameter Check:  @publication.
  7739.     ** Make sure that the publication exists.
  7740.     */
  7741.  
  7742.     if @publication IS NULL
  7743.         BEGIN
  7744.             RAISERROR (14043, 16, -1, '@publication')
  7745.             RETURN (1)
  7746.         END
  7747.  
  7748.     select @pubid = pubid, 
  7749.            @ad_guidname=ad_guidname, --with value NULL if this publication is not in AD.
  7750.            @snapshot_ready=snapshot_ready,
  7751.            @dynamic_filters_id=dynamic_filters,
  7752.            @sync_modeid = sync_mode, 
  7753.            @alt_snapshot_folder = alt_snapshot_folder,
  7754.            @enabled_for_internet = enabled_for_internet,
  7755.            @ftp_address = ftp_address,
  7756.            @snapshot_in_defaultfolder = snapshot_in_defaultfolder,
  7757.            @compress_snapshot = compress_snapshot,
  7758.            @in_ActiveD = case when ad_guidname is NULL then 0 else 1 end 
  7759.       FROM sysmergepublications 
  7760.      WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  7761.     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  7762.  
  7763.     if @pubid IS NULL
  7764.         BEGIN
  7765.             RAISERROR (20026, 16, -1, @publication)
  7766.             RETURN (1)
  7767.         END
  7768.     else
  7769.  
  7770.     /*
  7771.     ** Parameter Check:  @property.
  7772.     ** Check to make sure that @property is a valid property in
  7773.     ** sysmergepublications.
  7774.     */
  7775.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('description', 'status', 'retention', 'sync_mode', 'allow_push', 
  7776.         'allow_pull', 'allow_anonymous', 'enabled_for_internet', 'centralized_conflicts', 'snapshot_ready', 
  7777.         'snapshot_in_defaultfolder', 'alt_snapshot_folder', 'pre_snapshot_script', 'post_snapshot_script', 
  7778.         'compress_snapshot', 'ftp_address', 'ftp_port', 'ftp_subdirectory','ftp_login',
  7779.         'ftp_password', 'conflict_retention', 'allow_subscription_copy', 'allow_synctoalternate',
  7780.         'validate_subscriber_info','publish_to_activedirectory','dynamic_filters','max_concurrent_merge', 'max_concurrent_dynamic_snapshots') 
  7781.         BEGIN
  7782.             RAISERROR (21053, 16, -1)
  7783.             RETURN (1)
  7784.         END
  7785.  
  7786.  
  7787.     /*
  7788.     ** Parameter Check:
  7789.     ** If sync_method of the publication is character mode (an indication that it supports
  7790.     ** third party Subscribers), pre/post-snapshot setting must be null   
  7791.     **
  7792.     */
  7793.     IF @sync_modeid = 1 
  7794.     BEGIN
  7795.         IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pre_snapshot_script' OR
  7796.             LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'post_snapshot_script') AND
  7797.             @value IS NOT NULL AND @value <> ''
  7798.         BEGIN
  7799.             RAISERROR (21151, 16, -1)
  7800.             RETURN (1)
  7801.         END   
  7802.     END
  7803.  
  7804.     /*
  7805.     ** Parameter Check:
  7806.     ** If the Publication's alt_snapshot_folder setting is null 
  7807.     ** snapshot compression cannot be enabled
  7808.     */
  7809.     IF ((@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = '')) 
  7810.         AND LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'compress_snapshot'
  7811.         AND LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'   
  7812.     BEGIN
  7813.         RAISERROR (21157, 16, -1)        
  7814.         RETURN (1)
  7815.     END
  7816.  
  7817.     /* 
  7818.     ** Parameter Check:
  7819.     ** If enabled_for_internet is set to true, the publication must have a non-null
  7820.     ** ftp_address.
  7821.     */
  7822.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'enabled_for_internet' AND
  7823.        LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'true' AND 
  7824.        (@ftp_address IS NULL OR @ftp_address = N'')
  7825.     BEGIN
  7826.         RAISERROR(21158, 16, -1)
  7827.         RETURN (1)
  7828.     END
  7829.  
  7830.     /*
  7831.     ** .. and ftp_address cannot be null if the publication is enabled for 
  7832.     ** internet.
  7833.     */
  7834. /*
  7835.     IF @enabled_for_internet = 1 AND
  7836.       (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_address'
  7837.         AND (@value IS NULL OR @value = N''))
  7838.     BEGIN
  7839.         RAISERROR(21158, 16, -1)
  7840.         RETURN (1)
  7841.     END
  7842. */
  7843.     /*
  7844.     ** .. and 'alternate snapshot folder' is not null and
  7845.     ** 'snapshot in default folder' is false
  7846.     **
  7847.     */
  7848.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'enabled_for_internet' AND
  7849.         LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'true' AND
  7850.        (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N'')
  7851.     BEGIN
  7852.         RAISERROR(21159, 16, -1)
  7853.         RETURN (1)
  7854.     END 
  7855.  
  7856. /*
  7857.     IF @enabled_for_internet = 1 AND
  7858.        (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'alt_snapshot_folder' AND
  7859.         (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IS NULL OR LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N''))
  7860.     BEGIN
  7861.         RAISERROR(21159, 16, -1)
  7862.         RETURN (1)
  7863.     END  
  7864. */
  7865.  
  7866.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='validate_subscriber_info'
  7867.     begin
  7868.         if exists (select * from sysmergesubscriptions where pubid=@pubid and subid<>@pubid and status<>0)
  7869.             begin
  7870.                 raiserror(21501, 16, -1)
  7871.                 return (1)
  7872.             end    
  7873.     end
  7874.  
  7875.     /*
  7876.     ** Parameter Check:
  7877.     ** 'ftp_port' cannot be null
  7878.     */
  7879.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_port' AND @value IS NULL
  7880.     BEGIN
  7881.         RAISERROR (14043, 16, -1, @property)
  7882.         RETURN (1)
  7883.     END
  7884.  
  7885.     BEGIN TRAN changemergepublication    
  7886.     save tran changemergepublication
  7887.  
  7888.     /*
  7889.     ** Changing of the following properties would require a snapshot rerun, if snapshot is ready
  7890.     */
  7891.     if (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) like 'ftp%' OR LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('sync_mode', 'snapshot_in_defaultfolder',
  7892.             'alt_snapshot_folder', 'pre_snapshot_script', 'post_snapshot_script','compress_snapshot'))
  7893.     and @snapshot_ready>0
  7894.     begin
  7895.         if @force_invalidate_snapshot = 0
  7896.         begin
  7897.             raiserror(20607, 16, -1)
  7898.             goto UNDO
  7899.         end
  7900.         update sysmergepublications set snapshot_ready=2 where pubid=@pubid and snapshot_ready=1
  7901.         if @@ERROR<>0    GOTO UNDO
  7902.     end
  7903.  
  7904.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='dynamic_filters' and @snapshot_ready>0
  7905.     begin
  7906.         if @force_invalidate_snapshot = 0
  7907.         begin
  7908.             raiserror(20607, 16, -1)
  7909.             goto UNDO
  7910.         end
  7911.         if @force_reinit_subscription = 0
  7912.         begin
  7913.             raiserror(20608, 16, -1)
  7914.             goto UNDO
  7915.         end
  7916.         if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  7917.             select @dynamic_filters_id = 1
  7918.         else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'false' 
  7919.                select @dynamic_filters_id = 0
  7920.            else
  7921.                begin
  7922.                    raiserror(14137, 16, -1)
  7923.                    goto UNDO
  7924.                end
  7925.         update sysmergepublications set dynamic_filters=@dynamic_filters_id, snapshot_ready=2 where pubid=@pubid
  7926.         if @@ERROR<>0
  7927.             goto UNDO
  7928.         exec @retcode = sp_MSreinitmergepublication @publication
  7929.         if @retcode<>0 or @@ERROR<>0
  7930.             goto UNDO
  7931.     end
  7932.     
  7933.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='validate_subscriber_info'
  7934.     begin
  7935.         if @value is not NULL
  7936.         begin
  7937.             if @dynamic_filters_id = 0
  7938.                 begin
  7939.                     raiserror(21313, 16, -1)
  7940.                     GOTO UNDO
  7941.                 end
  7942.             exec ('select ' + @value)
  7943.             if @@ERROR<>0
  7944.                 begin
  7945.                     raiserror(21299, 16, -1, @value)
  7946.                     GOTO UNDO
  7947.                 end
  7948.         end
  7949.  
  7950.         UPDATE sysmergepublications  SET validate_subscriber_info = @value WHERE pubid = @pubid
  7951.         if @@ERROR <> 0 GOTO UNDO
  7952.     end
  7953.  
  7954.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('description')
  7955.         BEGIN
  7956.             UPDATE sysmergepublications  SET description = @value WHERE pubid = @pubid
  7957.             if @@ERROR <> 0 GOTO UNDO
  7958.         END
  7959.  
  7960.   
  7961.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status'
  7962.         BEGIN
  7963.  
  7964.             /*
  7965.             ** Check to make sure that we have a valid status.
  7966.             */
  7967.  
  7968.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('active', 'inactive')
  7969.                 BEGIN
  7970.                     RAISERROR (14012, 16, -1)
  7971.                     GOTO UNDO
  7972.                 END
  7973.  
  7974.             /*
  7975.             ** Determine the integer value for the status.
  7976.             */
  7977.  
  7978.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'active'
  7979.                 select @statusid = 1
  7980.             else
  7981.                 select @statusid = 0
  7982.  
  7983.             /*
  7984.             ** Update the publication with the new status.
  7985.             */
  7986.  
  7987.             UPDATE sysmergepublications SET status = @statusid WHERE pubid = @pubid
  7988.  
  7989.             if @@ERROR <> 0 GOTO UNDO
  7990.         END
  7991.  
  7992.  
  7993.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'retention'
  7994.         BEGIN
  7995.         /*
  7996.         ** Update the publication with the new replication frequency.
  7997.         */
  7998.  
  7999.         select @retention = CONVERT(int, @value)
  8000.  
  8001.         if @retention is NULL 
  8002.             select @retention = 0
  8003.  
  8004.            if @retention < 0
  8005.                begin
  8006.                    raiserror(20050, 16, -1, 0)
  8007.                    GOTO UNDO
  8008.                end
  8009.  
  8010.         UPDATE sysmergepublications set retention = @retention WHERE pubid = @pubid
  8011.         if @@ERROR <> 0 
  8012.             GOTO UNDO
  8013.  
  8014.         select @schemaversion = schemaversion from sysmergeschemachange
  8015.         if (@schemaversion is NULL)
  8016.             set @schemaversion = 1
  8017.         else
  8018.             select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  8019.             
  8020.         set @schemaguid = newid()
  8021.         set @artid = newid()
  8022.         set @schematype = 9 /* change retention */
  8023.         select @schematext = 'exec dbo.sp_MSchange_retention '+ '''' + convert(nchar(36),@pubid) + '''' + ',' + '''' + @value + ''''          
  8024.         exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  8025.             if @@ERROR<>0 or @retcode<>0 goto UNDO    
  8026.  
  8027.  
  8028.         END
  8029.  
  8030.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'conflict_retention'
  8031.         BEGIN
  8032.         /*
  8033.         ** Update the publication with the new conflict_retention value
  8034.         */
  8035.  
  8036.         select @retention = CONVERT(int, @value)
  8037.         if @@ERROR<>0
  8038.             GOTO UNDO
  8039.  
  8040.         if @value is NULL 
  8041.             select @retention = 0
  8042.  
  8043.            if @retention < 0
  8044.                begin
  8045.                    raiserror(20050, 16, -1, 0)
  8046.                    GOTO UNDO
  8047.                end
  8048.  
  8049.         UPDATE sysmergepublications
  8050.             SET conflict_retention = @retention
  8051.             WHERE pubid = @pubid
  8052.  
  8053.         if @@ERROR <> 0 
  8054.             GOTO UNDO
  8055.  
  8056.         END
  8057.  
  8058.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'max_concurrent_merge'
  8059.         BEGIN
  8060.         /*
  8061.         ** Update the publication property <max_concurrent_merge> with a new value
  8062.         */
  8063.  
  8064.         select @max_concurrent_merge = CONVERT(int, @value)
  8065.         if @max_concurrent_merge < 0    
  8066.         begin
  8067.             raiserror(21402, 16, -1, '@value')
  8068.             GOTO UNDO
  8069.         end
  8070.  
  8071.         UPDATE sysmergepublications
  8072.             SET max_concurrent_merge = @max_concurrent_merge
  8073.             WHERE pubid = @pubid
  8074.  
  8075.         if @@ERROR <> 0 
  8076.             GOTO UNDO
  8077.  
  8078.         END
  8079.  
  8080.  
  8081.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_mode'
  8082.         BEGIN
  8083.  
  8084.             /*
  8085.             ** Check for a valid synchronization method.
  8086.             */
  8087.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)='portable' select @value='character'
  8088.  
  8089.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('native', 'character', 'bcp native', 'bcp character')
  8090.                 begin
  8091.                 raiserror (20076, 16, -1)
  8092.                 GOTO UNDO
  8093.                 end
  8094.  
  8095.             /*
  8096.             ** Determine the integer value for the sync_mode.
  8097.             */
  8098.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('native', 'bcp native')
  8099.                 select @sync_modeid = 0
  8100.             else if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('character', 'bcp character')
  8101.                 select @sync_modeid = 1
  8102.  
  8103.             /*
  8104.             ** Update the publication with the new synchronization method.
  8105.             */
  8106.  
  8107.             UPDATE sysmergepublications
  8108.                SET sync_mode = @sync_modeid
  8109.              WHERE pubid = @pubid
  8110.  
  8111.             if @@ERROR <> 0 GOTO UNDO
  8112.         END
  8113.  
  8114.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'alt_snapshot_folder'
  8115.         BEGIN
  8116.             -- If the alt_snapshot_folder is set to '' or NULL,
  8117.             -- set the compress_snapshot bit to 0 and disable internet 
  8118.             -- support
  8119.   
  8120.             IF @value IS NULL OR @value = N''
  8121.             BEGIN
  8122.                 UPDATE sysmergepublications
  8123.                    SET alt_snapshot_folder = @value,
  8124.                        compress_snapshot = 0,
  8125.                        enabled_for_internet = 0
  8126.                  WHERE pubid = @pubid
  8127.             END
  8128.             ELSE
  8129.             BEGIN
  8130.                 UPDATE sysmergepublications
  8131.                    SET alt_snapshot_folder = @value
  8132.                  WHERE pubid = @pubid
  8133.             END
  8134.             IF @@error <> 0
  8135.             BEGIN
  8136.                GOTO UNDO
  8137.             END
  8138.         END
  8139.  
  8140.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'pre_snapshot_script'
  8141.         BEGIN
  8142.             UPDATE sysmergepublications
  8143.                SET pre_snapshot_script = @value
  8144.              WHERE pubid = @pubid
  8145.             IF @@error <> 0
  8146.             BEGIN
  8147.                GOTO UNDO
  8148.             END
  8149.         END
  8150.  
  8151.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'post_snapshot_script'
  8152.         BEGIN
  8153.             UPDATE sysmergepublications
  8154.                SET post_snapshot_script = @value
  8155.              WHERE pubid = @pubid
  8156.             IF @@error <> 0
  8157.             BEGIN
  8158.                GOTO UNDO
  8159.             END
  8160.         END
  8161.  
  8162.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_address'
  8163.         BEGIN
  8164.             IF @value IS NULL OR @value = N''    
  8165.             BEGIN
  8166.                 UPDATE sysmergepublications
  8167.                    SET ftp_address = @value,
  8168.                        enabled_for_internet = 0
  8169.                  WHERE pubid = @pubid
  8170.                 IF @@error <> 0
  8171.                 BEGIN
  8172.                     GOTO UNDO
  8173.                 END
  8174.             END
  8175.             ELSE
  8176.             BEGIN
  8177.                 UPDATE sysmergepublications
  8178.                    SET ftp_address = @value
  8179.                  WHERE pubid = @pubid
  8180.                 IF @@error <> 0
  8181.                 BEGIN
  8182.                     GOTO UNDO
  8183.                 END
  8184.             END
  8185.         END
  8186.             
  8187.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_port'
  8188.         BEGIN
  8189.             UPDATE sysmergepublications
  8190.                SET ftp_port = CONVERT(int, @value)
  8191.              WHERE pubid = @pubid
  8192.             IF @@error <> 0
  8193.             BEGIN
  8194.                GOTO UNDO
  8195.             END
  8196.         END
  8197.  
  8198.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_subdirectory'
  8199.         BEGIN
  8200.             UPDATE sysmergepublications
  8201.                SET ftp_subdirectory = @value
  8202.              WHERE pubid = @pubid
  8203.             IF @@error <> 0
  8204.             BEGIN
  8205.                GOTO UNDO
  8206.             END
  8207.         END
  8208.  
  8209.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_login'
  8210.         BEGIN
  8211.             UPDATE sysmergepublications
  8212.                SET ftp_login = @value
  8213.              WHERE pubid = @pubid
  8214.             IF @@error <> 0
  8215.             BEGIN
  8216.                GOTO UNDO
  8217.             END
  8218.         END
  8219.  
  8220.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_password'
  8221.         BEGIN
  8222.             SELECT @enc_ftp_password = NULL
  8223.             IF @value IS NOT NULL
  8224.             BEGIN
  8225.                 SELECT @enc_ftp_password = @value
  8226.                 EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  8227.                 IF @retcode <> 0
  8228.                 BEGIN
  8229.                     GOTO UNDO
  8230.                 END
  8231.             END
  8232.  
  8233.             UPDATE sysmergepublications
  8234.                SET ftp_password = @enc_ftp_password
  8235.              WHERE pubid = @pubid
  8236.             IF @@error <> 0
  8237.             BEGIN
  8238.                GOTO UNDO
  8239.             END
  8240.         END
  8241.  
  8242.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'max_concurrent_dynamic_snapshots'
  8243.         BEGIN
  8244.             SELECT @numeric_value = CONVERT(int, @value)
  8245.             IF @@ERROR<>0 OR @numeric_value < 0 OR @numeric_value IS NULL
  8246.             BEGIN
  8247.                 RAISERROR(21403, 16, -1)
  8248.                 GOTO UNDO
  8249.             END
  8250.  
  8251.             UPDATE sysmergepublications
  8252.                SET max_concurrent_dynamic_snapshots = @numeric_value
  8253.              WHERE pubid = @pubid
  8254.             IF @@error <> 0
  8255.             BEGIN 
  8256.                 GOTO UNDO
  8257.             END 
  8258.         END            
  8259.  
  8260.    if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publish_to_activedirectory'
  8261.    BEGIN
  8262.         if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  8263.         BEGIN
  8264.             RAISERROR (14137, 16, -1)
  8265.             GOTO UNDO
  8266.         END
  8267.  
  8268.         /* Is AD supported? */
  8269.         DECLARE @retval  INT
  8270.         EXECUTE @retval = master.dbo.xp_MSADEnabled
  8271.         if (@retval <> 0)
  8272.         begin
  8273.             RAISERROR(21254, 16, -1, @publication)
  8274.             RETURN (1)
  8275.         end
  8276.  
  8277.            if @in_ActiveD=0 and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)='true'
  8278.            BEGIN
  8279.             create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  8280.             if @@ERROR<>0
  8281.             begin
  8282.                 raiserror(21363, 16, -1, @publication, N'')
  8283.                 goto UNDO            
  8284.             end
  8285.             insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @db_name
  8286.             if @retcode <> 0 or @@ERROR<>0
  8287.             begin
  8288.                 declare @errorstring nvarchar(512)
  8289.                 select @errorstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory) 
  8290.                 drop table #guid_name_for_active_directory
  8291.                 if @errorstring is NULL
  8292.                     select @errorstring=N''
  8293.                 raiserror(21363, 16, -1, @publication, @errorstring)
  8294.                 GOTO UNDO
  8295.                end
  8296.             select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  8297.             if @ad_guidname is not NULL
  8298.             begin
  8299.                 update sysmergepublications set ad_guidname=@ad_guidname where pubid=@pubid
  8300.                 if @@ERROR<>0
  8301.                 begin
  8302.                     drop table #guid_name_for_active_directory
  8303.                     raiserror(21363, 16, -1, @publication, N'')
  8304.                     goto UNDO
  8305.                 end
  8306.             end
  8307.             drop table #guid_name_for_active_directory
  8308.            END
  8309.            else if @in_ActiveD=1 and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)='false'
  8310.            BEGIN
  8311.             exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @db_name, @ad_guidname
  8312.             if @@ERROR<>0 or @retcode<>0
  8313.             begin
  8314.                 raiserror(21369, 16, -1, @publication)    
  8315.                 goto UNDO
  8316.             end
  8317.             update sysmergepublications set ad_guidname=NULL where pubid=@pubid
  8318.             if @@ERROR<>0
  8319.             begin
  8320.                 raiserror(21369, 16, -1, @publication)    
  8321.                 goto UNDO
  8322.             end
  8323.            END
  8324.    END
  8325.  
  8326.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('allow_push', 'allow_pull', 'allow_anonymous', 'enabled_for_internet',
  8327.         'centralized_conflicts', 'snapshot_ready', 'snapshot_in_defaultfolder', 'compress_snapshot', 
  8328.         'allow_subscription_copy', 'allow_synctoalternate')
  8329.     BEGIN
  8330.  
  8331.         /*
  8332.         ** Check for a valid  value.
  8333.         */
  8334.  
  8335.         if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  8336.         BEGIN
  8337.             RAISERROR (14137, 16, -1)
  8338.             GOTO UNDO
  8339.         END
  8340.  
  8341.         /*
  8342.         ** set value bit
  8343.         */
  8344.         if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  8345.             select @value_bit = 1
  8346.         else 
  8347.             select @value_bit = 0
  8348.  
  8349.  
  8350.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_anonymous'
  8351.         BEGIN
  8352.             /* Update the allow_anonymous column */
  8353.             UPDATE sysmergepublications 
  8354.                 SET allow_anonymous = @value_bit
  8355.                 WHERE pubid = @pubid
  8356.             if @@error <> 0
  8357.             BEGIN
  8358.                GOTO UNDO
  8359.             END
  8360.  
  8361.         END
  8362.  
  8363.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_push'
  8364.         BEGIN
  8365.             /* Update the allow_push column */
  8366.             UPDATE sysmergepublications 
  8367.                 SET allow_push = @value_bit
  8368.                 WHERE pubid = @pubid
  8369.             if @@error <> 0
  8370.             BEGIN
  8371.                GOTO UNDO
  8372.             END
  8373.         END
  8374.  
  8375.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_pull'
  8376.         BEGIN
  8377.  
  8378.             /* Update the allow_pull column */
  8379.             UPDATE sysmergepublications 
  8380.                 SET allow_pull = @value_bit
  8381.                 WHERE pubid = @pubid
  8382.             if @@error <> 0
  8383.             BEGIN
  8384.                GOTO UNDO
  8385.             END
  8386.         END
  8387.  
  8388.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'centralized_conflicts'
  8389.         BEGIN
  8390.             /* Update the centralized_conflicts column */
  8391.             UPDATE sysmergepublications 
  8392.                 SET centralized_conflicts = @value_bit
  8393.                 WHERE pubid = @pubid
  8394.             if @@error <> 0
  8395.             BEGIN
  8396.                GOTO UNDO
  8397.             END
  8398.  
  8399.             if @value_bit=0 and @snapshot_ready>0
  8400.             begin            
  8401.             -- changing to decentralized conflict logging will require reinitialization but no snapshot rerun
  8402.                 if @force_reinit_subscription = 0
  8403.                 begin
  8404.                     raiserror(20608, 16, -1)
  8405.                     goto UNDO
  8406.                 end
  8407.                 exec @retcode = sp_MSreinitmergepublication @publication
  8408.                 if @@ERROR<>0 or @retcode<>0
  8409.                     goto UNDO
  8410.             end
  8411.         END
  8412.  
  8413.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'enabled_for_internet'
  8414.         BEGIN
  8415.             UPDATE sysmergepublications 
  8416.                SET enabled_for_internet = @value_bit
  8417.              WHERE pubid = @pubid
  8418.  
  8419.             IF @@error <> 0
  8420.             BEGIN
  8421.                GOTO UNDO
  8422.             END
  8423.         END
  8424.  
  8425.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'snapshot_ready'
  8426.         BEGIN
  8427.             /* Update the allow_anonymous column */
  8428.             UPDATE sysmergepublications 
  8429.                 SET snapshot_ready = @value_bit
  8430.                 WHERE pubid = @pubid
  8431.             if @@error <> 0
  8432.             BEGIN
  8433.                GOTO UNDO
  8434.             END
  8435.  
  8436.         END
  8437.  
  8438.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'snapshot_in_defaultfolder'
  8439.         BEGIN
  8440.             -- snapshot_in_defaultfolder = 1 is only meaningful when
  8441.             -- alt_snapshot_folder is non-null, otherwise 
  8442.             -- a copy of the snapshot files is always kept
  8443.             -- at the publisher's working directory 
  8444.     
  8445.             UPDATE sysmergepublications 
  8446.                SET snapshot_in_defaultfolder = @value_bit
  8447.              WHERE pubid = @pubid
  8448.             IF @@error <> 0
  8449.             BEGIN
  8450.                 GOTO UNDO
  8451.             END                
  8452.  
  8453.             -- Bump up the compatibility level if we are
  8454.             -- setting snapshot_in_defaultfolder to 0
  8455.             -- and compression is enabled. i.e. only 
  8456.             -- a compressed snapshot will be generated
  8457.             -- Note that alt_snapshot_folder is implicitly
  8458.             -- specified for the publication
  8459.             IF @value_bit = 0 and @compress_snapshot = 1 
  8460.             BEGIN
  8461.                 EXEC @retcode = sp_MSBumpupCompLevel @pubid, 40
  8462.                 IF @@ERROR<>0 OR @retcode<>0
  8463.                     GOTO UNDO
  8464.             END
  8465.  
  8466.         END
  8467.         
  8468.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'compress_snapshot'
  8469.         BEGIN
  8470.  
  8471.             UPDATE sysmergepublications
  8472.                SET compress_snapshot = @value_bit
  8473.              WHERE pubid = @pubid
  8474.             IF @@error <> 0
  8475.             BEGIN
  8476.                 GOTO UNDO
  8477.             END
  8478.  
  8479.             -- See comment for 'snapshot_in_defaultfolder'
  8480.             IF @value_bit = 1 and @snapshot_in_defaultfolder = 0
  8481.             BEGIN
  8482.                 EXEC @retcode = sp_MSBumpupCompLevel @pubid, 40
  8483.                 IF @@ERROR<>0 OR @retcode<>0
  8484.                     GOTO UNDO
  8485.             END
  8486.         END
  8487.  
  8488.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_subscription_copy'
  8489.         BEGIN
  8490.             /* Update the allow_subscription_copy column */
  8491.             UPDATE sysmergepublications 
  8492.                 SET allow_subscription_copy = @value_bit
  8493.                 WHERE pubid = @pubid
  8494.             if @@error <> 0
  8495.             BEGIN
  8496.                GOTO UNDO
  8497.             END
  8498.         END
  8499.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_synctoalternate'
  8500.         BEGIN
  8501.             /* Update the allow_synctoalternate column */
  8502.             UPDATE sysmergepublications 
  8503.                 SET allow_synctoalternate = @value_bit
  8504.                 WHERE pubid = @pubid
  8505.             if @@error <> 0
  8506.             BEGIN
  8507.                GOTO UNDO
  8508.             END
  8509.         END
  8510.     END
  8511.  
  8512.     /*
  8513.     ** Update merge publication property at distributor side if necessaray 
  8514.     */
  8515.     
  8516.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('description','allow_push', 'allow_pull', 'allow_anonymous','retention', 'allow_subscription_copy')
  8517.     BEGIN
  8518.  
  8519.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('allow_push', 'allow_pull', 'allow_anonymous','allow_subscription_copy')
  8520.             
  8521.         /* Translate values */
  8522.         BEGIN            
  8523.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  8524.                 SELECT @value = '1'
  8525.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'false'
  8526.                     SELECT @value = '0'
  8527.         END
  8528.         /*
  8529.         ** Get distribution server information for remote RPC call.
  8530.         */
  8531.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  8532.            @distribdb   = @distribdb OUTPUT
  8533.         IF @@ERROR <> 0 or @retcode <> 0
  8534.             BEGIN
  8535.                 GOTO UNDO
  8536.             END
  8537.  
  8538.         SELECT @dbname =  DB_NAME()
  8539.         
  8540.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  8541.             '.dbo.sp_MSchange_publication'
  8542.     
  8543.         EXECUTE @retcode = @distproc
  8544.             @publisher = @@SERVERNAME,
  8545.             @publisher_db = @dbname,
  8546.             @publication = @publication,
  8547.             @property = @property,
  8548.             @value = @value
  8549.  
  8550.         IF @@ERROR <> 0 OR @retcode <> 0
  8551.         BEGIN
  8552.             GOTO UNDO
  8553.         END
  8554.     END
  8555.  
  8556.     COMMIT TRAN
  8557.  
  8558.     --update its registration in active directory
  8559.     if @in_ActiveD=1 and LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('description','allow_pull', 'allow_anonymous')
  8560.     begin
  8561.         create table #guid_name_for_ADupdate(ad_guidname sysname collate database_default null)
  8562.         if @@ERROR<>0
  8563.         begin
  8564.             goto FAILURE
  8565.         end
  8566.         insert into #guid_name_for_ADupdate exec @retcode = master.dbo.sp_ActiveDirectory_Obj N'UPDATE', N'PUBLICATION', @publication, @db_name, @ad_guidname
  8567.         if @@ERROR<>0 or @retcode<>0
  8568.         begin
  8569.             goto FAILURE                     
  8570.            end
  8571.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_ADupdate
  8572.         if @ad_guidname is not NULL
  8573.         begin
  8574.             update sysmergepublications set ad_guidname=@ad_guidname where pubid=@pubid
  8575.             if @@ERROR<>0
  8576.                 goto FAILURE                     
  8577.         end
  8578.         drop table #guid_name_for_ADupdate
  8579.     end
  8580.  
  8581.     /*
  8582.     ** Return succeed.
  8583.     */
  8584.     
  8585.     RAISERROR (14077, 10, -1)
  8586.     RETURN (0)
  8587. FAILURE:
  8588.     drop table #guid_name_for_ADupdate
  8589.     raiserror(21371, 10, -1, @publication)
  8590.     return (1)   
  8591.  
  8592. UNDO: 
  8593.     if @@TRANCOUNT > 0
  8594.     begin
  8595.         ROLLBACK TRANSACTION changemergepublication
  8596.         COMMIT TRANSACTION
  8597.     end
  8598. GO
  8599. exec dbo.sp_MS_marksystemobject sp_changemergepublication 
  8600. go
  8601.  
  8602. grant execute on dbo.sp_changemergepublication to public
  8603. go
  8604.  
  8605. raiserror('Creating procedure sp_helpmergepublication', 0,1)
  8606. GO
  8607.  
  8608. CREATE PROCEDURE sp_helpmergepublication (
  8609.     @publication    sysname = '%',    /* The publication name */
  8610.     @found          int         = NULL  OUTPUT,
  8611.     @publication_id uniqueidentifier = NULL OUTPUT,
  8612.     @reserved       nvarchar(20) = NULL
  8613.     ) AS
  8614.  
  8615.     SET NOCOUNT ON
  8616.  
  8617.     /*
  8618.     ** Declarations.
  8619.     */
  8620.  
  8621.     declare @retcode            int
  8622.     declare @no_row             bit
  8623.     declare @our_srvid          int
  8624.     declare @has_subscription   bit
  8625.     /*
  8626.     ** Initializations.
  8627.     */
  8628.     select @has_subscription = 0
  8629.  
  8630.     if @found is NULL 
  8631.     BEGIN
  8632.         select @no_row=0
  8633.     END
  8634.     else
  8635.     BEGIN
  8636.         select @no_row=1
  8637.     END
  8638.     select @found       = 0
  8639.     select @our_srvid = max(srvid) from master.dbo.sysservers where UPPER(srvname) = UPPER(@@SERVERNAME) collate database_default
  8640.  
  8641.     
  8642.     /*
  8643.     ** Running sp_help is OK from everywhere, whether enabled for publishing or not
  8644.     */
  8645.     
  8646.     IF not exists (select * from sysobjects where name='sysmergesubscriptions')
  8647.         RETURN (0)
  8648.  
  8649.  
  8650.     /*
  8651.     ** Parameter Check:  @publication.
  8652.     ** Check to make sure that there are some publications
  8653.     ** to display.
  8654.     */
  8655.  
  8656.     if @publication IS NULL
  8657.         BEGIN
  8658.             RAISERROR (14043, 16, -1, '@publication')
  8659.             RETURN (1)
  8660.         END
  8661.  
  8662.     IF LOWER(@reserved collate SQL_Latin1_General_CP1_CS_AS) = 'internal'
  8663.         GOTO SelectPubs
  8664.     
  8665.     if  NOT EXISTS (select * FROM sysmergepublications pub, sysmergesubscriptions sub
  8666.         WHERE pub.name like @publication  
  8667.             and UPPER(pub.publisher)=UPPER(@@servername) 
  8668.             and pub.publisher_db=db_name() 
  8669.             and sub.pubid = pub.pubid  
  8670.             and sub.srvid = @our_srvid 
  8671.             and sub.db_name = db_name())
  8672.         BEGIN
  8673.             select @found = 0
  8674.             RETURN (0) 
  8675.         END
  8676.     else
  8677.         BEGIN
  8678.             select @found = 1
  8679.             select @publication_id = pubid FROM sysmergepublications 
  8680.                 WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  8681.             if exists (select * from sysmergesubscriptions where pubid<>subid and pubid in 
  8682.                 (select pubid from sysmergepublications where name like @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()))
  8683.                 select @has_subscription = 1
  8684.             if @no_row <> 0
  8685.                 RETURN(0)
  8686.         END
  8687.  
  8688. SelectPubs:
  8689.  
  8690.     CREATE TABLE #tab1 (
  8691.         id                      int                 identity NOT NULL,
  8692.         name                    sysname             collate database_default not null,
  8693.         description             nvarchar(255)       collate database_default null,
  8694.         status                  tinyint             NOT NULL,
  8695.         retention               int                 NULL,
  8696.         sync_mode               tinyint             NULL,
  8697.         allow_push              int                 NOT NULL,
  8698.         allow_pull              int                 NOT NULL,
  8699.         allow_anonymous         int                 NOT NULL,
  8700.         centralized_conflicts   int                 NOT NULL,
  8701.         priority                float(8)            NOT NULL,
  8702.         snapshot_ready          tinyint             NOT NULL,
  8703.         publication_type        int                 NULL,
  8704.         pubid                   uniqueidentifier    NOT NULL,
  8705.         snapshot_jobid          binary(16)          NULL,
  8706.         enabled_for_internet    int                 NULL,
  8707.         dynamic_filters         int                 NULL,
  8708.         has_subscription        bit                 NULL,
  8709.         -- Portable snapshot support
  8710.         snapshot_in_defaultfolder       bit default 1       NOT NULL,
  8711.         alt_snapshot_folder     nvarchar(255)       collate database_default null,
  8712.         -- Pre/post-snapshot commands
  8713.         pre_snapshot_script     nvarchar(255)       collate database_default null,
  8714.         post_snapshot_script    nvarchar(255)       collate database_default null,
  8715.         -- Snapshot compression
  8716.         compress_snapshot       bit default 0       NOT NULL,
  8717.         -- Post 7.0 FTP support
  8718.         ftp_address             sysname             collate database_default null,
  8719.         ftp_port                int                 NOT NULL,
  8720.         ftp_subdirectory        nvarchar(255)       collate database_default null,
  8721.         ftp_login               sysname             collate database_default null,
  8722.         conflict_retention        int                    NULL,
  8723.         keep_partition_changes    int                    NULL,
  8724.         allow_subscription_copy int                 NULL,
  8725.         allow_synctoalternate     int                 NULL,
  8726.         validate_subscriber_info nvarchar(500)        collate database_default null,
  8727.         backward_comp_level        int                    not null default 10, --defaulted to 70 server
  8728.         publish_to_activedirectory            bit                    null,
  8729.         max_concurrent_merge    int                    NULL,
  8730.         max_concurrent_dynamic_snapshots int  NOT NULL default 0
  8731.         )
  8732.  
  8733.     /* This is valid at all sites - used for decentralized conflicts */
  8734.     IF LOWER(@reserved collate SQL_Latin1_General_CP1_CS_AS) = 'internal'
  8735.         begin
  8736.             INSERT into #tab1(name, description, status, retention, sync_mode, 
  8737.                     allow_push, allow_pull, allow_anonymous, centralized_conflicts, 
  8738.                     priority, snapshot_ready, publication_type, pubid, snapshot_jobid, 
  8739.                     enabled_for_internet, 
  8740.                     dynamic_filters, snapshot_in_defaultfolder, alt_snapshot_folder, pre_snapshot_script,
  8741.                     post_snapshot_script, compress_snapshot, ftp_address, ftp_port, 
  8742.                     ftp_subdirectory, ftp_login, conflict_retention, 
  8743.                     keep_partition_changes, allow_subscription_copy, allow_synctoalternate, 
  8744.                     validate_subscriber_info,backward_comp_level, publish_to_activedirectory, max_concurrent_merge, max_concurrent_dynamic_snapshots)
  8745.             select  pubs.name, pubs.description, pubs.status, pubs.retention, pubs.sync_mode, 
  8746.                     pubs.allow_push, pubs.allow_pull, pubs.allow_anonymous, pubs.centralized_conflicts, 
  8747.                     subs.priority, pubs.snapshot_ready, pubs.publication_type, pubs.pubid, replinfo.snapshot_jobid,
  8748.                     pubs.enabled_for_internet, 
  8749.                     pubs.dynamic_filters,
  8750.                     pubs.snapshot_in_defaultfolder,
  8751.                     pubs.alt_snapshot_folder,
  8752.                     pubs.pre_snapshot_script,
  8753.                     pubs.post_snapshot_script,
  8754.                     pubs.compress_snapshot,
  8755.                     pubs.ftp_address,
  8756.                     pubs.ftp_port,
  8757.                     pubs.ftp_subdirectory,
  8758.                     pubs.ftp_login,
  8759.                     pubs.conflict_retention,
  8760.                     pubs.keep_before_values,
  8761.                     pubs.allow_subscription_copy,
  8762.                     pubs.allow_synctoalternate,
  8763.                     pubs.validate_subscriber_info,
  8764.                     pubs.backward_comp_level,
  8765.                     case when pubs.ad_guidname is NULL then 0 else 1 end,
  8766.                     pubs.max_concurrent_merge,
  8767.                     pubs.max_concurrent_dynamic_snapshots
  8768.             FROM    sysmergesubscriptions   subs,
  8769.                     sysmergepublications    pubs,
  8770.                     MSmerge_replinfo        replinfo
  8771.                     WHERE pubs.name LIKE @publication
  8772.                         AND UPPER(pubs.publisher)=UPPER(@@servername) 
  8773.                         AND pubs.publisher_db=db_name()
  8774.                         AND subs.subid = pubs.pubid
  8775.                         AND replinfo.repid = pubs.pubid
  8776.                         AND subs.subscriber_type = 1
  8777.             ORDER BY name
  8778.         end
  8779.     /* This is valid only at publishers and republishers */
  8780.     else
  8781.         begin
  8782.             INSERT into #tab1(name, description, status, retention, sync_mode, 
  8783.                     allow_push, allow_pull, allow_anonymous, centralized_conflicts, 
  8784.                     priority, snapshot_ready, publication_type, pubid, snapshot_jobid, 
  8785.                     enabled_for_internet,
  8786.                     dynamic_filters, has_subscription,
  8787.                     snapshot_in_defaultfolder, alt_snapshot_folder, pre_snapshot_script, 
  8788.                     post_snapshot_script, compress_snapshot, ftp_address,
  8789.                     ftp_port, ftp_subdirectory, ftp_login, conflict_retention, 
  8790.                     keep_partition_changes, allow_subscription_copy, allow_synctoalternate, 
  8791.                     validate_subscriber_info, backward_comp_level, publish_to_activedirectory,max_concurrent_merge,max_concurrent_dynamic_snapshots)
  8792.             select  pubs.name, pubs.description, pubs.status, pubs.retention, pubs.sync_mode, 
  8793.                     pubs.allow_push, pubs.allow_pull, pubs.allow_anonymous, pubs.centralized_conflicts, 
  8794.                     subs.priority, pubs.snapshot_ready, pubs.publication_type, pubs.pubid, replinfo.snapshot_jobid,
  8795.                     pubs.enabled_for_internet,
  8796.                     pubs.dynamic_filters, case when exists (select * from sysmergesubscriptions where pubid<>subid and pubid in 
  8797.                                                 (select in_pubs.pubid from sysmergepublications in_pubs where in_pubs.name = pubs.name 
  8798.                                                     and UPPER(in_pubs.publisher)=UPPER(@@servername) and in_pubs.publisher_db=db_name()))
  8799.                                           then 1
  8800.                                           else 0 end,
  8801.                     pubs.snapshot_in_defaultfolder, pubs.alt_snapshot_folder,
  8802.                     pubs.pre_snapshot_script, pubs.post_snapshot_script,
  8803.                     pubs.compress_snapshot, pubs.ftp_address,
  8804.                     pubs.ftp_port, pubs.ftp_subdirectory,
  8805.                     pubs.ftp_login,
  8806.                     pubs.conflict_retention,
  8807.                     pubs.keep_before_values,
  8808.                     pubs.allow_subscription_copy,
  8809.                     pubs.allow_synctoalternate,
  8810.                     pubs.validate_subscriber_info,
  8811.                     pubs.backward_comp_level,
  8812.                     case when pubs.ad_guidname is NULL then 0 else 1 end ,
  8813.                     pubs.max_concurrent_merge,
  8814.                     pubs.max_concurrent_dynamic_snapshots
  8815.             FROM    sysmergesubscriptions   subs,
  8816.                     sysmergepublications    pubs,
  8817.                     MSmerge_replinfo        replinfo
  8818.                     WHERE pubs.name LIKE @publication
  8819.                          and UPPER(pubs.publisher)=UPPER(@@servername) 
  8820.                          and pubs.publisher_db=db_name()
  8821.                         AND subs.subid = pubs.pubid
  8822.                         AND replinfo.repid = pubs.pubid
  8823.                         AND subs.subscriber_type = 1
  8824.                         AND subs.srvid = @our_srvid 
  8825.                         AND subs.db_name = db_name()
  8826.             ORDER BY name
  8827.         end
  8828.     if @@ERROR <> 0 
  8829.         RETURN (1)
  8830.  
  8831.     update #tab1 set snapshot_ready=0 where snapshot_ready>1
  8832.     if @@ERROR<>0
  8833.         RETURN (1)
  8834.     select * FROM #tab1
  8835.     RETURN (0)
  8836. go
  8837. exec dbo.sp_MS_marksystemobject sp_helpmergepublication 
  8838. go
  8839.  
  8840. grant execute on dbo.sp_helpmergepublication to public
  8841. go
  8842.  
  8843.  
  8844. raiserror('Creating procedure sp_dropmergepublication', 0,1)
  8845. GO
  8846.  
  8847. CREATE PROCEDURE sp_dropmergepublication(
  8848.         @publication sysname,      /* The publication name */
  8849.         @ignore_distributor bit = 0,
  8850.         @reserved bit = 0
  8851.         ) AS
  8852.  
  8853.     set nocount on
  8854.     /*
  8855.     ** Declarations.
  8856.     */
  8857.     declare @ad_guidname        sysname
  8858.     declare @pubid              uniqueidentifier
  8859.     declare @article            sysname
  8860.     declare @cmd                nvarchar(255)
  8861.     declare @retcode            int
  8862.     declare @distproc           nvarchar(300)
  8863.     declare @distributor        sysname
  8864.     declare @distribdb          sysname
  8865.     declare @working_dir        varchar(255)
  8866.     declare @working_dir_drive  varchar(255)
  8867.     declare @pub_dir            nvarchar(255)
  8868.     declare @db_name            sysname
  8869.     declare @implicit_transaction    int
  8870.     declare @close_cursor_at_commit int
  8871.     declare @dynamic_filters        bit
  8872.     declare @alt_snapshot_folder nvarchar(255)
  8873.     declare @pub_alt_snapshot_folder nvarchar(255)
  8874.  
  8875.     select @close_cursor_at_commit = 0
  8876.     select @implicit_transaction = 0
  8877.     /*
  8878.     ** Save setting values first before changing them
  8879.     */
  8880.     IF (@reserved = 0)
  8881.     BEGIN
  8882.         SELECT @implicit_transaction = @@options & 2
  8883.         SELECT @close_cursor_at_commit = @@options & 4
  8884.         SET IMPLICIT_TRANSACTIONS OFF
  8885.         SET CURSOR_CLOSE_ON_COMMIT OFF
  8886.     END
  8887.  
  8888.     set @ad_guidname = NULL
  8889.     /*
  8890.     ** Initializations.
  8891.     */  
  8892.     select @db_name = db_name()
  8893.  
  8894.     /*
  8895.     ** Security Check
  8896.     */
  8897.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  8898.     IF @@ERROR <> 0 or @retcode <> 0
  8899.         return (1)
  8900.  
  8901.     /* make sure current database is enabled for merge replication */
  8902.     exec @retcode=dbo.sp_MSCheckmergereplication
  8903.     if @@ERROR<>0 or @retcode<>0
  8904.         return (1)
  8905.  
  8906.     if LOWER(@publication) = 'all'
  8907.         BEGIN
  8908.  
  8909.             declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name 
  8910.                 FROM sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() 
  8911.                     FOR READ ONLY
  8912.             
  8913.             OPEN hC1
  8914.             FETCH hC1 INTO @publication
  8915.             WHILE (@@fetch_status <> -1)
  8916.                 BEGIN
  8917.                     EXECUTE dbo.sp_dropmergepublication @publication=@publication,
  8918.                         @ignore_distributor = @ignore_distributor,
  8919.                         @reserved = 1
  8920.  
  8921.                     FETCH hC1 INTO @publication
  8922.                 END
  8923.             CLOSE hC1
  8924.             DEALLOCATE hC1
  8925.             RETURN (0)
  8926.         END
  8927.  
  8928.     if @publication IS NULL
  8929.         BEGIN
  8930.             RAISERROR (14003, 16, -1)
  8931.             RETURN (1)
  8932.         END
  8933.     /*
  8934.     ** Get the @pubid.
  8935.     */
  8936.     if NOT EXISTS (select * FROM sysmergepublications 
  8937.         WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
  8938.         BEGIN
  8939.             RAISERROR (20026, 16, -1, @publication)
  8940.             RETURN (1)
  8941.         END
  8942.     select @pubid = pubid,
  8943.            @dynamic_filters = @dynamic_filters,
  8944.            @alt_snapshot_folder = alt_snapshot_folder 
  8945.       FROM sysmergepublications 
  8946.         WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  8947.  
  8948.     select @ad_guidname=ad_guidname FROM sysmergepublications 
  8949.             WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()    
  8950.     
  8951.     /* 
  8952.     ** Ignore external publications
  8953.     */
  8954.     if exists (select * from sysmergesubscriptions where subid=@pubid 
  8955.         and pubid=@pubid and db_name<>db_name())
  8956.     RETURN (0)
  8957.  
  8958.     /*
  8959.     ** Check to make sure that there are push or pull subscriptions on the publication.
  8960.     */
  8961.     if EXISTS (select * FROM sysmergesubscriptions  subs, 
  8962.                     sysmergepublications                pubs, 
  8963.                     MSmerge_replinfo                    repinfo
  8964.                 WHERE   pubs.name = @publication
  8965.                     AND UPPER(pubs.publisher)=UPPER(@@servername) 
  8966.                     AND pubs.publisher_db=db_name()
  8967.                     AND subs.pubid = pubs.pubid
  8968.                     AND subs.status <> 2  -- Having a deleted subscription row is fine
  8969.                     AND repinfo.repid <> @pubid
  8970.                     AND subs.subid <> subs.partnerid)
  8971.         BEGIN
  8972.             RAISERROR (14005, 16, -1)
  8973.             RETURN (1)
  8974.         END
  8975.  
  8976.  
  8977.     begin tran
  8978.     save TRANSACTION dropmergepublication
  8979.  
  8980.     /*
  8981.     ** delete on-demand user script, if any
  8982.     */
  8983.     if exists (select * from sysmergeschemachange where schematype=46 and pubid=@pubid)
  8984.         begin
  8985.             exec @retcode=sp_MSremove_userscript @pubid, 1
  8986.             --we may not want to do error checking here
  8987.         end
  8988.     
  8989.     /*
  8990.     ** Delete all articles from the publication.
  8991.     */
  8992.  
  8993.     update sysmergepublications set snapshot_ready=0 where pubid=@pubid --so that articles can be dropped
  8994.     if @@ERROR<>0
  8995.         goto FAILURE
  8996.     EXECUTE @retcode = dbo.sp_dropmergearticle @publication = @publication, @article = 'all',
  8997.         @ignore_distributor = @ignore_distributor
  8998.  
  8999.     if @@ERROR <> 0 OR @retcode <> 0
  9000.         begin
  9001.             RAISERROR (20040, 16, -1, @publication)
  9002.             goto FAILURE
  9003.         end
  9004.  
  9005.     /*
  9006.     ** Delete sync task of Publication.
  9007.     */
  9008.     execute @retcode = dbo.sp_MSdropmergepub_snapshot @publication = @publication,
  9009.         @ignore_distributor = @ignore_distributor
  9010.  
  9011.     if @@ERROR <> 0 OR @retcode <> 0
  9012.         begin
  9013.             RAISERROR (20010, 16, -1, @publication)
  9014.             goto FAILURE
  9015.         end
  9016.  
  9017.     /*
  9018.     ** Remove my own subscription from sysmergesubscriptions.
  9019.     */
  9020.     if exists (select * from sysmergesubscriptions where subid = @pubid)
  9021.         begin
  9022.             DELETE from sysmergesubscriptions WHERE subid = @pubid
  9023.             if @@ERROR <> 0
  9024.                 goto FAILURE
  9025.         end         
  9026.  
  9027.     if exists (select * from MSmerge_replinfo where repid = @pubid)
  9028.         begin
  9029.             DELETE from MSmerge_replinfo WHERE repid = @pubid
  9030.             if @@ERROR <> 0
  9031.                 goto FAILURE
  9032.         end             
  9033.  
  9034.     /*
  9035.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  9036.     */
  9037.     if @ignore_distributor = 0
  9038.     begin
  9039.         /*
  9040.         ** Get distribution server information for remote RPC call.
  9041.         */
  9042.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  9043.                                            @distribdb = @distribdb OUTPUT,
  9044.                                            @directory = @working_dir OUTPUT
  9045.         IF @@ERROR <> 0 OR  @retcode <> 0
  9046.             BEGIN
  9047.                 RAISERROR (14071, 16, -1)
  9048.                 goto FAILURE
  9049.             END
  9050.  
  9051.         /*
  9052.         ** Drop the publication info from the distributor
  9053.         */
  9054.         select @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  9055.             '.dbo.sp_MSdrop_publication'
  9056.         EXECUTE @retcode = @distproc
  9057.             @publisher = @@SERVERNAME,
  9058.             @publisher_db = @db_name,
  9059.             @publication = @publication
  9060.  
  9061.         if @@ERROR <> 0 OR @retcode <> 0
  9062.         begin
  9063.             goto FAILURE
  9064.         end
  9065.  
  9066.         /*
  9067.         ** If alternate snapshot folder is specified for this publication,
  9068.         ** try to remove the publication's snapshot folder underneath the
  9069.         ** the alternate snapshot location in Distributor's context
  9070.         */
  9071.         if @alt_snapshot_folder is not null and
  9072.            @alt_snapshot_folder <> N''
  9073.         begin
  9074.  
  9075.             /* Append publication specific folder name */
  9076.             if substring(@alt_snapshot_folder,len(@alt_snapshot_folder),1)<>
  9077.                 N'\' 
  9078.             begin
  9079.                 select @alt_snapshot_folder = @alt_snapshot_folder + N'\'
  9080.             end 
  9081.  
  9082.             -- UNC version
  9083.             select @pub_alt_snapshot_folder = @alt_snapshot_folder + N'unc\' + fn_replcomposepublicationsnapshotfolder(@@servername,@db_name,@publication) collate database_default
  9084.             select @distproc = fn_replquotename(RTRIM(@distributor)) collate database_default + '.'  + fn_replquotename(@distribdb) collate database_default + 
  9085.                 '.dbo.sp_MSreplremoveuncdir'
  9086.             -- Ignore errors as the snapshot folder may not exist at all
  9087.             EXECUTE @distproc
  9088.                 @dir = @pub_alt_snapshot_folder
  9089.  
  9090.             -- FTP-enabled version
  9091.             select @pub_alt_snapshot_folder = @alt_snapshot_folder + N'ftp\' + fn_replcomposepublicationsnapshotfolder(@@servername,@db_name,@publication) collate database_default
  9092.             select @distproc = fn_replquotename(RTRIM(@distributor)) collate database_default + '.'  + fn_replquotename(@distribdb) collate database_default + 
  9093.                 '.dbo.sp_MSreplremoveuncdir'
  9094.             -- Ignore errors as the snapshot folder may not exist at all
  9095.             EXECUTE @distproc
  9096.                 @dir = @pub_alt_snapshot_folder
  9097.         end         
  9098.     end
  9099.  
  9100.     /* Remove all dynamic snapshot jobs of this publication */
  9101.     exec @retcode = sp_MSdropmergedynamicsnapshotjob 
  9102.         @publication = @publication,
  9103.         @ignore_distributor = @ignore_distributor
  9104.  
  9105.     if @@ERROR <> 0 OR @retcode <> 0
  9106.     begin
  9107.         goto FAILURE
  9108.     end
  9109.  
  9110.     /*
  9111.     ** Execute the cleanup routine for the publication
  9112.     */
  9113.     exec dbo.sp_MSpublicationcleanup @publisher=@@SERVERNAME, 
  9114.             @publisher_db = @db_name,
  9115.             @publication = @publication
  9116.     
  9117.     if @@ERROR <> 0
  9118.         goto FAILURE
  9119.  
  9120.     DECLARE @retval  INT
  9121.     EXECUTE @retval = master.dbo.xp_MSADEnabled
  9122.     if @ad_guidname is not NULL 
  9123.     begin
  9124.         if @retval = 0
  9125.         begin
  9126.             exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @db_name, @ad_guidname
  9127.             if @@ERROR<>0 or @retcode<>0
  9128.             begin
  9129.                 raiserror(21369, 16, -1, @publication)
  9130.                 goto FAILURE
  9131.             end
  9132.         end
  9133.         else
  9134.         begin
  9135.             RAISERROR(21254, 16, -1, @publication)
  9136.             GOTO FAILURE
  9137.         end
  9138.     end
  9139.  
  9140.     COMMIT TRANSACTION
  9141.     /*
  9142.     ** Set back original settings
  9143.     */    
  9144.     IF @reserved = 0
  9145.     BEGIN
  9146.         IF @implicit_transaction <>0 
  9147.             SET IMPLICIT_TRANSACTIONS ON
  9148.         IF @close_cursor_at_commit <>0 
  9149.             SET CURSOR_CLOSE_ON_COMMIT ON
  9150.     END
  9151.     return (0)
  9152.  
  9153. FAILURE:            
  9154.     RAISERROR (14006, 16, -1)
  9155.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  9156.     if @@TRANCOUNT > 0
  9157.     begin
  9158.         ROLLBACK TRANSACTION dropmergepublication
  9159.         COMMIT TRANSACTION
  9160.     end
  9161.     /*
  9162.     ** Set back original settings
  9163.     */    
  9164.     IF @reserved = 0
  9165.     BEGIN
  9166.         IF @implicit_transaction <>0 
  9167.             SET IMPLICIT_TRANSACTIONS ON
  9168.         IF @close_cursor_at_commit <>0 
  9169.             SET CURSOR_CLOSE_ON_COMMIT ON
  9170.     END        
  9171.     RETURN (1)
  9172. go
  9173. exec dbo.sp_MS_marksystemobject sp_dropmergepublication
  9174. go
  9175.  
  9176. grant execute on dbo.sp_dropmergepublication to public
  9177. go
  9178.  
  9179. raiserror('Creating procedure sp_mergearticlecolumn', 0, 1)
  9180. GO
  9181.  
  9182. CREATE PROCEDURE sp_mergearticlecolumn (
  9183.         @publication sysname,           /* The publication name */
  9184.         @article sysname,               /* The article name */
  9185.         @column sysname = NULL,         /* The column name */
  9186.         @operation nvarchar(4) = 'add',      /* Add or delete a column */
  9187.         @schema_replication nvarchar(5) = 'false',    /* reserved for internal use */
  9188.         @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  9189.         @force_reinit_subscription bit = 0    /* Force reinit subscription */
  9190.         ) AS
  9191.  
  9192.     SET NOCOUNT ON
  9193.     /*
  9194.     ** Declarations.
  9195.     */
  9196.     declare @mergepublish    int
  9197.     declare @iscomputed        int
  9198.     declare @xtype            int
  9199.     declare @sync_mode        int
  9200.     declare @index_cnt        int
  9201.     declare @v_unique_constraint            int
  9202.     declare @v_unique_index            int
  9203.     declare @indid            int
  9204.     declare @in_partition     bit
  9205.     declare @colid    int
  9206.     DECLARE @cnt int, @idx int  /* Loop counter, index */
  9207.     DECLARE @columnid smallint   /* Columnid-1 = bit to set */
  9208.     DECLARE @columns binary(128)         /* Temporary storage for the converted column */
  9209.     DECLARE @pubid uniqueidentifier                  /* Publication identification number */
  9210.     DECLARE @retcode int                /* Return code for stored procedures */
  9211.     DECLARE @artid uniqueidentifier
  9212.     declare @object_view     sysname
  9213.     declare @filter_clause nvarchar(1000)
  9214.     DECLARE @objid int            /* Article base table id */    
  9215.     declare @tmp_artid    uniqueidentifier
  9216.     declare @tmp_object    sysname
  9217.     declare @publisher    sysname
  9218.     declare @publisher_db    sysname
  9219.     declare @pkkey        sysname
  9220.     declare @conflict_table    sysname
  9221.     declare @status_value    int
  9222.     declare @column_list    nvarchar(4000)
  9223.     declare @ins_conflict_proc sysname
  9224.     declare @qual_source_object    nvarchar(270)
  9225.     declare @qual_object_view    nvarchar(270)
  9226.     declare @qual_tmp_object    nvarchar(270)
  9227.     declare @source_object    nvarchar(300)
  9228.     declare @v_foreign_key int
  9229.     declare @quoted_source_object nvarchar(270)
  9230.     select @publisher = @@SERVERNAME
  9231.     select @publisher_db = db_name()
  9232.     /*
  9233.     ** Security Check
  9234.     */
  9235.     exec @retcode = dbo.sp_MSreplcheck_publish
  9236.     if @@ERROR <> 0 or @retcode <> 0
  9237.         return(1)
  9238.  
  9239.     select @mergepublish = 0x4000
  9240.     select @v_unique_index      = 2         -- status in sysindexes
  9241.     select @v_foreign_key = 3            -- status in sysconstraints
  9242.     select @v_unique_constraint      = 4096 --status in sysindexes
  9243.  
  9244.     /*
  9245.     ** Check to see if the database has been activated for publication.
  9246.     */
  9247.  
  9248.     IF ( (SELECT category & 4 FROM master..sysdatabases WHERE name = DB_NAME() collate database_default) = 0 )
  9249.     BEGIN
  9250.         RAISERROR (14013, 16, -1)
  9251.         RETURN (1)
  9252.     END
  9253.  
  9254.     /*
  9255.     ** Parameter Check:  @publication.
  9256.     ** Make sure that the publication exists and that it conforms to the
  9257.     ** rules for identifiers.
  9258.     */
  9259.  
  9260.     IF @publication IS NULL
  9261.         BEGIN
  9262.             RAISERROR (14043, 16, -1, '@publication')
  9263.             RETURN (1)
  9264.         END
  9265.  
  9266.     EXECUTE @retcode = dbo.sp_validname @publication
  9267.     IF @retcode <> 0 or @@ERROR<>0
  9268.             RETURN (1)
  9269.  
  9270.     SELECT @pubid = pubid, @sync_mode = sync_mode FROM sysmergepublications WHERE name = @publication 
  9271.                                                         and LOWER(publisher)=LOWER(@publisher)
  9272.                                                         and publisher_db = @publisher_db
  9273.                                                                     
  9274.     IF @pubid IS NULL
  9275.         BEGIN
  9276.             RAISERROR (20026, 11, -1, @publication)
  9277.             RETURN (1)
  9278.         END
  9279.  
  9280.     /*
  9281.     ** Parameter Check:  @article.
  9282.     ** Check to make sure that the article exists in the publication.
  9283.     */
  9284.  
  9285.     IF @article IS NULL
  9286.         BEGIN
  9287.             RAISERROR (14043, 16, -1, '@article')
  9288.             RETURN (1)
  9289.         END
  9290.  
  9291.     EXECUTE @retcode = dbo.sp_validname @article
  9292.     IF @retcode <> 0 or @@ERROR<>0
  9293.             RETURN (1)
  9294.  
  9295.     /*
  9296.     ** Make sure the article exists.
  9297.     */
  9298.     SELECT @artid = artid FROM sysmergearticles
  9299.        WHERE pubid = @pubid AND name = @article
  9300.     IF @artid IS NULL
  9301.         BEGIN
  9302.             RAISERROR (20027, 16, -1, @article)
  9303.             RETURN (1)
  9304.         END
  9305.     
  9306.     /*
  9307.     ** Parameter Check:  @column.
  9308.     ** Check to make sure that the column exists and conforms to the rules
  9309.     ** for identifiers.
  9310.     */
  9311.  
  9312.     IF @column IS NOT NULL
  9313.         BEGIN
  9314.             EXECUTE @retcode = dbo.sp_validname @column
  9315.             IF @@ERROR <> 0 OR @retcode <> 0
  9316.             RETURN (1)
  9317.         END
  9318.  
  9319.     /*
  9320.     ** Parameter Check:  @operation.
  9321.     ** The operation can be either 'add' or 'drop'.
  9322.     */
  9323.     IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('add', 'drop')
  9324.         BEGIN
  9325.             RAISERROR (14019, 16, -1)
  9326.             RETURN (1)
  9327.         END
  9328.         
  9329.     /*
  9330.     ** column name can not be null for 'drop' operation. OK for 'add' operation
  9331.     */
  9332.     IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS)='drop' and @column is NULL
  9333.         BEGIN
  9334.             RAISERROR(14043, 16, -1, '@column')
  9335.             RETURN (1)
  9336.         END    
  9337.     /*
  9338.     ** Can not drop non-identity, non-timestamp, non-computed columns that are not nullable and have no default value
  9339.     */
  9340.     SELECT @status_value=status, @objid = objid, 
  9341.         @source_object = object_name(objid) FROM sysmergearticles WHERE artid = @artid
  9342.     select @colid=colid from syscolumns where id=@objid and name=@column
  9343.     if not exists (select * from syscolumns where id = @objid and name=@column and (isnullable=1 
  9344.                     OR type_name(xtype)='timestamp' OR iscomputed=1))
  9345.         and not exists (select * from sysconstraints where id=@objid and colid=@colid and status & 5 = 5)
  9346.             and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS)='drop' and LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9347.             and ColumnProperty(@objid, @column, 'IsIdentity') <> 1
  9348.         BEGIN
  9349.             RAISERROR(21165, 16, -1, @column)
  9350.             return (1)
  9351.         END
  9352.         
  9353.     
  9354.     if LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  9355.     begin        
  9356.         select @indid = indid from sysindexes where id = @objid and (status & 2048) <> 0    /* PK index */
  9357.         select @index_cnt = 1
  9358.         while (@index_cnt <= 16)
  9359.             begin
  9360.                 select @pkkey = INDEX_COL(@source_object, @indid, @index_cnt)
  9361.                 if @pkkey is NULL
  9362.                     break
  9363.                 if @pkkey=@column
  9364.                     begin
  9365.                         raiserror(21250, 16, -1, @column)
  9366.                         return (1)
  9367.                     end
  9368.                 select @index_cnt = @index_cnt + 1
  9369.             end
  9370.     
  9371.         /*
  9372.         ** Check for unique index defined on this column - to disallow such a column from being dropped
  9373.         */    
  9374.         if exists (select * from sysindexes where id=@objid 
  9375.                     and (status & @v_unique_index = @v_unique_index 
  9376.                         or status & @v_unique_constraint = @v_unique_constraint))
  9377.         begin
  9378.             declare @keys varbinary(816)
  9379.             declare @i         int
  9380.             declare #check_unique CURSOR LOCAL FAST_FORWARD for 
  9381.             select indid from sysindexes where id=@objid 
  9382.                 and (status & @v_unique_index = @v_unique_index 
  9383.                     or status & @v_unique_constraint = @v_unique_constraint)
  9384.             open #check_unique
  9385.             fetch #check_unique into @indid
  9386.             while (@@fetch_status<>-1)
  9387.             begin
  9388.                 SELECT @i = 1
  9389.                 WHILE (@i <= 16)
  9390.                 BEGIN
  9391.                         SELECT @pkkey = INDEX_COL(@source_object, @indid, @i)
  9392.                         if @pkkey is NULL
  9393.                             break
  9394.                         if @pkkey=@column
  9395.                         BEGIN
  9396.                             if LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='true'
  9397.                                 raiserror(21265, 16, -1, @column, @source_object)
  9398.                             else
  9399.                                 raiserror(21347, 16, -1, @column)                            
  9400.                             close #check_unique
  9401.                             deallocate #check_unique
  9402.                             return (1)
  9403.                         END
  9404.                         select @i = @i + 1
  9405.                 END    
  9406.                 fetch #check_unique into @indid
  9407.             end
  9408.             close #check_unique
  9409.             deallocate #check_unique
  9410.         end
  9411.  
  9412.         /*
  9413.         ** Check for foreign key constraints
  9414.         */
  9415.         if exists (select * from sysconstraints where status & @v_foreign_key=@v_foreign_key and id=@objid)
  9416.         begin
  9417.             if @column in (select name from syscolumns where id=@objid and colid in
  9418.                 (select colid from sysconstraints where status & @v_foreign_key=@v_foreign_key and id=@objid))
  9419.             begin
  9420.                 raiserror(21513, 16, -1, @column)
  9421.                 return (1)
  9422.             end
  9423.         end
  9424.     end
  9425.  
  9426.     begin tran
  9427.     save TRANSACTION articlecolumn
  9428.  
  9429.     /*
  9430.     ** Make sure that the column <columns> is not NULL - if NULL set to 0x00.
  9431.     */
  9432.     SELECT @columns = columns FROM sysmergearticles WHERE artid = @artid and pubid=@pubid
  9433.     IF @columns IS NULL
  9434.         UPDATE sysmergearticles SET columns = 0x00 WHERE artid = @artid and pubid=@pubid
  9435.     
  9436.     /*
  9437.     ** If no columns are specified, or if NULL is specified, set all
  9438.     ** the bits in the 'columns' column so all columns will be included, 
  9439.     */
  9440.     IF @column IS NULL
  9441.     BEGIN
  9442.         SELECT @cnt = max(colid), @idx = 1 FROM syscolumns WHERE id = @objid 
  9443.         SELECT @columns = NULL
  9444.         WHILE @idx <= @cnt
  9445.         BEGIN
  9446.             /* to make sure column holes will not be included */
  9447.             if exists (select * from syscolumns where colid=@idx and id=@objid and 
  9448.                 (@sync_mode=0 OR (iscomputed<>1 and type_name(xtype) <>'timestamp')))
  9449.                 begin
  9450.                     exec sp_MSsetbit @bm=@columns OUTPUT, @coltoadd=@idx, @toset = 1
  9451.                     if @@ERROR<>0 or @retcode<>0
  9452.                         goto FAILURE
  9453.                     update syscolumns set colstat=colstat | @mergepublish where id=@objid and colid=@idx
  9454.                     if @@ERROR<>0
  9455.                         goto FAILURE
  9456.  
  9457.                 end
  9458.             SELECT @idx = @idx + 1
  9459.         END
  9460.         UPDATE sysmergearticles SET columns = @columns WHERE name = @article AND pubid = @pubid
  9461.         if @sync_mode=1 and exists (select * from syscolumns where id=@objid and (iscomputed=1 or type_name(xtype)='timestamp'))
  9462.             UPDATE sysmergearticles SET vertical_partition = 1 WHERE name = @article AND pubid = @pubid
  9463.     END
  9464.     ELSE
  9465.     BEGIN
  9466.         /* if @column is NULL, meanning all columns are in, do not bump up version to Shiloh. */
  9467.         if LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9468.             raiserror(21351, 10, -1, @publication)
  9469.         else
  9470.             raiserror(21352, 10, -1, @publication)
  9471.         exec @retcode = sp_MSBumpupCompLevel @pubid, 40
  9472.         if @@ERROR<>0 or @retcode<>0
  9473.             GOTO FAILURE
  9474.  
  9475.         SELECT @columnid = colid, @iscomputed=iscomputed, @xtype=xtype  
  9476.             FROM syscolumns WHERE id = @objid AND name = @column
  9477.         IF ((@@error <> 0) OR (@columnid IS NULL))
  9478.         BEGIN
  9479.             RAISERROR (21166, 16, -1, @column)
  9480.             GOTO FAILURE
  9481.         END
  9482.  
  9483.         /*
  9484.         ** for character mode publications, we do not allow adding computed column or timestamp columns
  9485.         ** into the vertical parititioning. 
  9486.         */
  9487.         if @sync_mode=1 and (@iscomputed = 1 or type_name(@xtype) ='timestamp') and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'add'
  9488.         begin
  9489.             if LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9490.                 begin
  9491.                     raiserror(21269, 16, -1)
  9492.                     GOTO FAILURE
  9493.                 end
  9494.             else
  9495.             begin    
  9496.                 if @@TRANCOUNT >0 
  9497.                 begin
  9498.                     ROLLBACK TRANSACTION articlecolumn
  9499.                     COMMIT TRAN
  9500.                 end
  9501.                 return (0)
  9502.             end
  9503.         end
  9504.         
  9505.         if ColumnProperty(@objid, @column, 'isrowguidcol') = 1 and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  9506.         begin
  9507.             RAISERROR(21162, 16, -1)
  9508.             GOTO FAILURE
  9509.         end
  9510.  
  9511.         exec @in_partition = sp_MStestbit @bm=@columns, @coltotest=@columnid
  9512.  
  9513.         if @in_partition=1 and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'add' and LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9514.         begin
  9515.             RAISERROR(21335, 10, -1, @column)
  9516.             GOTO FAILURE
  9517.         end
  9518.         
  9519.         if @in_partition=0 and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop' and LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9520.         begin
  9521.             RAISERROR(21336, 10, -1, @column)
  9522.             GOTO FAILURE
  9523.         end
  9524.  
  9525.         SELECT @columns = columns, @filter_clause=subset_filterclause, @ins_conflict_proc=ins_conflict_proc, @conflict_table=conflict_table FROM sysmergearticles WHERE name = @article AND pubid = @pubid
  9526.         IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'add'
  9527.             begin
  9528.                 exec @retcode = sp_MSsetbit @bm = @columns OUTPUT, @coltoadd=@columnid, @toset=1
  9529.                 if @@ERROR<>0 or @retcode<>0 
  9530.                     GOTO FAILURE
  9531.                 update syscolumns set colstat=colstat | @mergepublish where id=@objid and colid=@colid
  9532.                 if @@ERROR<>0
  9533.                     goto FAILURE
  9534.             end
  9535.         ELSE
  9536.             begin
  9537.                 
  9538.                 exec @retcode = sp_MSsetbit @bm = @columns OUTPUT, @coltoadd=@columnid, @toset=0
  9539.                 if @@ERROR<>0 or @retcode<>0 
  9540.                     GOTO FAILURE
  9541.                 if @columns = 0x00
  9542.                     begin
  9543.                         raiserror(21345, 16, -1)
  9544.                         goto FAILURE
  9545.                     end
  9546.                 exec @retcode = sp_MSclearcolumnbit @pubid, @artid, @column
  9547.                 if @@ERROR<>0 or @retcode<>0
  9548.                     goto FAILURE
  9549.             end
  9550.  
  9551.         /*
  9552.         ** Set vertical_partitioning flag so that publication view would be re-generated even
  9553.         ** if there is not subsetfilters nor join filters
  9554.         */
  9555.         UPDATE sysmergearticles  SET columns = @columns, vertical_partition=1 
  9556.             WHERE name = @article AND pubid = @pubid
  9557.         IF @@ERROR <> 0
  9558.         BEGIN
  9559.             RAISERROR (14021, 16, -1)
  9560.             GOTO FAILURE
  9561.         END
  9562.  
  9563.         select @column_list = NULL
  9564.         
  9565.         /*
  9566.         ** check to see if that column can be dropped based on current article's filter clause
  9567.         ** and if the article is involved in any join_filter_clauses - to make sure the drop of
  9568.         ** one column does not cripple any such joins
  9569.         */ 
  9570.         if ((@filter_clause is not NULL and @filter_clause <>'' ) or 
  9571.             exists (select * from sysmergesubsetfilters where pubid=@pubid and 
  9572.             (artid=@artid or join_articlename=@article))) and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  9573.         begin
  9574.             exec @retcode = sp_MSgetcolumnlist @pubid, @column_list OUTPUT, @objid
  9575.             if @@ERROR<>0 or @retcode<>0
  9576.                 GOTO FAILURE
  9577.             select @object_view='TEMP_VIEW_' + @source_object  --@source_object is not quoted
  9578.             select @qual_object_view=quotename(@object_view)
  9579.  
  9580.             exec @retcode = sp_MSget_qualified_name @objid, @qual_source_object OUTPUT
  9581.             if @@ERROR<>0 or @retcode<>0
  9582.                 goto FAILURE
  9583.             select @quoted_source_object=QUOTENAME(@source_object)
  9584.             
  9585.             exec ('create view ' + @qual_object_view + ' as select ' + @column_list + ' from ' + @qual_source_object)
  9586.             if @@ERROR<>0
  9587.                 GOTO FAILURE
  9588.             if @filter_clause is not NULL and @filter_clause <>'' 
  9589.             begin
  9590.                 exec ('declare @test int select @test=1 from ' + @qual_object_view + ' ' + @quoted_source_object + ' where ' + @filter_clause)
  9591.                 if @@ERROR<>0
  9592.                     begin
  9593.                         exec('drop view ' + @qual_object_view)
  9594.                         raiserror(21256, 16, -1, @filter_clause, @source_object)
  9595.                         GOTO FAILURE
  9596.                     end
  9597.             end            
  9598.         end
  9599.         
  9600.         /*
  9601.         ** Check to make sure dropping a column will not breaking any other articles that using current article as join_article
  9602.         */
  9603.         if exists (select * from sysmergesubsetfilters where pubid=@pubid and 
  9604.             (artid=@artid or join_articlename=@article)) and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  9605.         begin
  9606.             declare @join_articlename sysname
  9607.             declare per_article CURSOR LOCAL FAST_FORWARD FOR 
  9608.                 select artid, join_filterclause, join_articlename from sysmergesubsetfilters 
  9609.                     where pubid=@pubid and (join_articlename=@article or artid=@artid)
  9610.             for READ ONLY
  9611.             open per_article
  9612.             fetch per_article into @tmp_artid, @filter_clause, @join_articlename
  9613.             while (@@fetch_status<>-1)
  9614.             begin
  9615.                 if @artid<>@tmp_artid
  9616.                     select @tmp_object=object_name(objid) from sysmergearticles where pubid=@pubid and artid=@tmp_artid
  9617.                 else
  9618.                     select @tmp_object=object_name(objid) from sysmergearticles where pubid=@pubid and name=@join_articlename
  9619.                 select @qual_tmp_object=QUOTENAME(@tmp_object)
  9620.                 if @tmp_object is not NULl and @tmp_object<>''
  9621.                     begin
  9622.                         exec ('declare @test int select @test=1 from ' + @qual_object_view + ' ' + @quoted_source_object + ', ' + @qual_tmp_object + ' where ' + @filter_clause)                    
  9623.                         if @@ERROR<>0
  9624.                         begin
  9625.                             close per_article
  9626.                             deallocate per_article
  9627.                             raiserror(21256, 16, -1, @filter_clause, @source_object)
  9628.                             GOTO FAILURE
  9629.                         end
  9630.                     end
  9631.                 fetch per_article into @tmp_artid, @filter_clause, @join_articlename    
  9632.             end
  9633.             close per_article
  9634.             deallocate per_article        
  9635.         end            
  9636.     END   
  9637.  
  9638.     /*
  9639.     ** if snapshot is ready, change it to obsolete to force another snapshot run.    
  9640.     ** Note this is the third value of snapshot_ready. 0 for not ready, 1 for OK, 2 for obsolete
  9641.     */   
  9642.     IF EXISTS (SELECT * FROM sysmergepublications WHERE pubid=@pubid and snapshot_ready>0) 
  9643.             and LOWER(@schema_replication collate SQL_Latin1_General_CP1_CS_AS)='false'
  9644.         BEGIN
  9645.             update sysmergearticles set status=1, conflict_table=NULL where pubid=@pubid and artid=@artid and status<>5 and status <>6
  9646.             if @@ERROR<>0
  9647.                 goto FAILURE
  9648.         /*
  9649.         ** Force a re-generation of conflict table and its ins_proc
  9650.         */
  9651.             if object_id(@ins_conflict_proc) is not NULL
  9652.                 begin
  9653.                     exec ('drop proc ' + @ins_conflict_proc)
  9654.                     if @@ERROR<>0
  9655.                         goto FAILURE
  9656.                 end
  9657.             if object_id(@conflict_table) is not NULL
  9658.                 begin
  9659.                     exec ('drop table ' + @conflict_table)
  9660.                     if @@ERROR<>0
  9661.                         goto FAILURE
  9662.                 end
  9663.             /*
  9664.             ** make sure we know we really want to do this.
  9665.             */
  9666.             if @force_invalidate_snapshot = 0
  9667.                 begin
  9668.                     raiserror(20607, 16, -1)
  9669.                     goto FAILURE
  9670.                 end
  9671.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  9672.             if @@ERROR<>0
  9673.                 goto FAILURE
  9674.  
  9675.             if @force_reinit_subscription = 0 and @status_value<>5 --5 is the value for new_inactive
  9676.                 begin
  9677.                     raiserror(20608, 16, -1)
  9678.                     goto FAILURE
  9679.                 end
  9680.  
  9681.             --do a global re
  9682.             
  9683.             if @force_reinit_subscription = 1
  9684.                 begin
  9685.                     --global reinitialization will bump up backward-comp-level to SP2.
  9686.                 exec @retcode = sp_MSreinitmergepublication @publication
  9687.                 if @retcode<>0 or @@ERROR<>0
  9688.                     goto FAILURE
  9689.                 end
  9690.             /*
  9691.             ** Even for vertical partitioning on new article - we do not need to bumpup backward-comp-level
  9692.             **
  9693.             else
  9694.                 begin    --bump up the backward-comp-level so that only 80 subscribers can use it.
  9695.                 exec @retcode = sp_MSBumpupCompLevel @pubid, 40
  9696.                 if @@ERROR<>0 or @retcode<>0
  9697.                     GOTO FAILURE
  9698.                 end
  9699.             */
  9700.         END
  9701.  
  9702.     COMMIT TRANSACTION
  9703.     if exists (select * from sysobjects where id = object_id(@qual_object_view))
  9704.         begin
  9705.             exec ('drop view ' + @qual_object_view)
  9706.         end
  9707.     return (0)
  9708. FAILURE:
  9709.  
  9710.     if @@TRANCOUNT >0 
  9711.         begin
  9712.             ROLLBACK TRANSACTION articlecolumn
  9713.             COMMIT TRAN
  9714.         end
  9715.  
  9716.     if exists (select * from sysobjects where id = object_id(@qual_object_view))
  9717.         begin
  9718.             exec ('drop view ' + @qual_object_view)
  9719.         end
  9720.  
  9721.     return (1)
  9722. go
  9723.  
  9724. EXEC dbo.sp_MS_marksystemobject sp_mergearticlecolumn
  9725. GO
  9726.  
  9727. raiserror('Creating procedure sp_helpmergearticlecolumn', 0, 1)
  9728. GO
  9729.  
  9730. CREATE PROCEDURE sp_helpmergearticlecolumn (
  9731.     @publication sysname,            /* The publication name */
  9732.     @article    sysname              /* The article name */
  9733.     ) AS
  9734.     SET NOCOUNT ON
  9735.  
  9736.     /*
  9737.     ** Declarations.
  9738.     */
  9739.     declare @colid        int
  9740.     declare @colmax        int
  9741.     declare @colname    sysname
  9742.     declare @published    bit
  9743.     declare @columns     binary(128)
  9744.     declare @pubid         uniqueidentifier
  9745.     declare @retcode     int
  9746.     declare @objid        int
  9747.     declare @publisher    sysname
  9748.     declare @publisher_db    sysname
  9749.  
  9750.     select @publisher = @@SERVERNAME
  9751.     select @publisher_db = db_name()
  9752.  
  9753.     /*
  9754.     ** Parameter Check: @article.
  9755.     ** The @article name must conform to the rules for identifiers.
  9756.     */
  9757.  
  9758.     IF @article IS NULL
  9759.         BEGIN
  9760.             RAISERROR (14043, 16, -1, '@article')
  9761.             RETURN (1)
  9762.         END
  9763.     EXECUTE @retcode = dbo.sp_validname @article
  9764.     IF @retcode <> 0 or @@ERROR<>0
  9765.         RETURN (1)
  9766.  
  9767.     /*
  9768.     ** Parameter Check: @publication.
  9769.     ** The @publication name must conform to the rules for identifiers.
  9770.     */
  9771.     IF @publication IS NULL
  9772.         BEGIN
  9773.             RAISERROR (14043, 16, -1, '@publication')
  9774.             RETURN (1)
  9775.         END
  9776.     EXECUTE @retcode = dbo.sp_validname @publication
  9777.     IF @retcode <> 0 or @@ERROR<>0
  9778.     RETURN (1)
  9779.     
  9780.     SELECT @pubid = pubid FROM sysmergepublications WHERE name = @publication 
  9781.                                                           and LOWER(publisher)=LOWER(@publisher)
  9782.                                                           and publisher_db = @publisher_db
  9783.     IF @pubid IS NULL
  9784.         BEGIN
  9785.             RAISERROR (20026, 11, -1, @publication)
  9786.             RETURN (1)
  9787.         END
  9788.  
  9789.     /*
  9790.     ** Parameter Check:  @article, @publication.
  9791.     ** Check to make sure that the article exists in this publication.
  9792.     */
  9793.  
  9794.     IF NOT EXISTS (SELECT * FROM sysmergearticles WHERE pubid = @pubid AND name = @article)
  9795.         BEGIN
  9796.             RAISERROR (20027, 11, -1, @article)
  9797.             RETURN (1)
  9798.         END
  9799.  
  9800.     SELECT @columns = columns, @objid=objid FROM sysmergearticles
  9801.         WHERE name = @article AND pubid = @pubid
  9802.  
  9803.     create table #tmp (column_id int, column_name sysname collate database_default, published bit)
  9804.     select TOP 1 @colid = colid from syscolumns where id = @objid order by colid ASC
  9805.     select TOP 1 @colmax = colid from syscolumns where id = @objid order by colid DESC
  9806.     while (@colid <= @colmax)
  9807.     begin
  9808.     if exists (select * from syscolumns where id = @objid and colid = @colid)
  9809.         begin
  9810.             select @colname = name from syscolumns where id=@objid and colid=@colid
  9811.             exec @retcode = sp_MStestbit @bm=@columns, @coltotest=@colid
  9812.             if @retcode<>0
  9813.                 select @published=1
  9814.             else
  9815.                 select @published=0
  9816.             insert into #tmp values(@colid, @colname, @published)
  9817.         end
  9818.         select @colid=@colid + 1
  9819.     end
  9820.     select * from #tmp
  9821.     drop table #tmp
  9822.     go
  9823.  
  9824. EXEC dbo.sp_MS_marksystemobject sp_helpmergearticlecolumn
  9825. GO
  9826. grant execute on dbo.sp_helpmergearticlecolumn to public
  9827. go
  9828.         
  9829. raiserror('Creating procedure sp_MSreinitmergepublication', 0, 1)
  9830. GO
  9831.  
  9832. create procedure sp_MSreinitmergepublication
  9833.     @publication    sysname,
  9834.     @upload_first    bit = 0
  9835. AS
  9836.     declare @pubid                uniqueidentifier
  9837.     declare @schematext         nvarchar(4000)
  9838.     declare @schemaversion         int
  9839.     declare @schemaguid            uniqueidentifier
  9840.     declare @schematype            int
  9841.     declare @publisher            sysname
  9842.     declare @retcode            int
  9843.     declare @publisher_db        sysname
  9844.  
  9845.     set nocount on
  9846.     /* 
  9847.     ** Security Check.
  9848.     ** We use login_name stored in syssubscriptions to manage security 
  9849.     */
  9850.     exec @retcode = dbo.sp_MSreplcheck_publish
  9851.     if @@ERROR <> 0 or @retcode <> 0
  9852.         return(1)
  9853.         
  9854.     select @publisher=@@servername
  9855.     select @publisher_db = db_name()
  9856.     
  9857.     select @pubid=pubid from sysmergepublications 
  9858.         where name=@publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  9859.  
  9860.     raiserror(21353,10, -1,@publication)
  9861.     exec @retcode=sp_MSBumpupCompLevel @pubid, 30 --for 7.0 SP2, which has limited support for this
  9862.     if @@ERROR<>0 or @retcode<>0        
  9863.         return (1)
  9864.     select @schematext = 'exec sp_MSreinit_hub '+ QUOTENAME(@publisher) + ', ' + QUOTENAME(@publisher_db) + ', ' + QUOTENAME(@publication) + ', ' + convert(nvarchar, @upload_first)
  9865.     select @schemaversion = schemaversion from sysmergeschemachange
  9866.     if (@schemaversion is NULL)
  9867.         set @schemaversion = 1
  9868.     else
  9869.         select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange        
  9870.     set @schemaguid = newid()
  9871.     if @upload_first = 0
  9872.         set @schematype = 12 /* reinit_all */
  9873.     else
  9874.         set @schematype = 14 /* reinit_with_upload*/
  9875.     exec @retcode=sp_MSinsertschemachange @pubid, @schemaguid, @schemaversion, @schemaguid, @schematype, @schematext
  9876.     if @@ERROR<>0 or @retcode<>0 
  9877.         return (1)
  9878.         
  9879.     update MSmerge_replinfo set schemaversion=0, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
  9880.         where repid in (select subid from sysmergesubscriptions where subid<>pubid and pubid=@pubid and subscription_type=0)
  9881.     if @@ERROR<>0 
  9882.         return (1)
  9883.  
  9884.     -- set all article status to inactive as a starting point - which sort or cleanup the newly added status
  9885.     -- 5 and 6.
  9886.  
  9887.     if @upload_first=0 --do not reset status is upload_first is true. Otherwise, 
  9888.                        --creating triggers would fail.    
  9889.     begin
  9890.         update sysmergearticles set status=1 where pubid=@pubid 
  9891.         if @@ERROR<>0
  9892.             return (1)
  9893.     end
  9894.     update MSmerge_replinfo set schemaversion=-1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
  9895.         where repid in (select subid from sysmergesubscriptions where subid<>pubid and pubid=@pubid and subscription_type>0)
  9896.         
  9897.     if @@ERROR<>0 
  9898.         return (1)
  9899.  
  9900. GO
  9901.  
  9902. exec dbo.sp_MS_marksystemobject sp_MSreinitmergepublication
  9903. go  
  9904.  
  9905. grant execute on dbo.sp_MSreinitmergepublication to public
  9906. go
  9907.  
  9908. raiserror('Creating procedure sp_MSreinit_hub', 0, 1)
  9909. GO
  9910. create procedure sp_MSreinit_hub
  9911.     @publisher        sysname,
  9912.     @publisher_db    sysname,
  9913.     @publication    sysname,
  9914.     @upload_first    bit
  9915. AS
  9916.     declare @retcode            int
  9917.     declare @pubid                uniqueidentifier
  9918.     declare @hub_pubname        sysname
  9919.     declare @hub_publisher        sysname
  9920.     declare @hub_publisher_db    sysname
  9921.     declare @hub_pubid            uniqueidentifier
  9922.     declare @schematext         nvarchar(4000)
  9923.     declare @schemaversion         int
  9924.     declare @schemaguid            uniqueidentifier
  9925.     declare @schematype            int
  9926.  
  9927.     /* 
  9928.     ** Security Check.
  9929.     ** We use login_name stored in syssubscriptions to manage security 
  9930.     */
  9931.     exec @retcode = dbo.sp_MSreplcheck_publish
  9932.     if @@ERROR <> 0 or @retcode <> 0
  9933.         return(1)
  9934.     
  9935.     select @pubid=pubid from sysmergepublications 
  9936.         where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  9937.     BEGIN TRAN
  9938.     SAVE TRAN reinithub
  9939.     
  9940.     /* Find all publications that are being republished at the subscriber */
  9941.     declare reinit_hub CURSOR LOCAL FAST_FORWARD FOR select DISTINCT p.pubid, p.name, p.publisher, p.publisher_db FROM sysmergepublications p
  9942.         where UPPER(p.publisher)=UPPER(@@SERVERNAME) and p.publisher_db=db_name()
  9943.             and exists (select * from sysmergearticles where (objid in 
  9944.                     (select objid from sysmergearticles where pubid=@pubid)) and (objid in 
  9945.                     (select objid from sysmergearticles where pubid=p.pubid))) and p.pubid<>@pubid
  9946.     FOR READ ONLY
  9947.     open reinit_hub
  9948.     fetch reinit_hub into @hub_pubid, @hub_pubname, @hub_publisher, @hub_publisher_db
  9949.     while (@@fetch_status<>-1)
  9950.     begin
  9951.         if @upload_first=1
  9952.         begin
  9953.             update sysmergesubscriptions set status=5 where pubid=@hub_pubid
  9954.             if @@ERROR<>0
  9955.                 goto FAILURE
  9956.         end
  9957.         select @schematext = 'exec sp_MSreinit_hub '+ QUOTENAME(@hub_publisher) + ', ' + QUOTENAME(@hub_publisher_db) + ', ' + QUOTENAME(@hub_pubname) + ', ' + convert(nvarchar, @upload_first)
  9958.         select @schemaversion = schemaversion from sysmergeschemachange
  9959.         if (@schemaversion is NULL)
  9960.             set @schemaversion = 1
  9961.         else
  9962.             select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange        
  9963.         set @schemaguid = newid()
  9964.         if @upload_first=0
  9965.             set @schematype = 12 /* reinit_all */
  9966.         else
  9967.             set @schematype = 14 /*reinitwithupload */
  9968.         exec @retcode=sp_MSinsertschemachange @hub_pubid, @schemaguid, @schemaversion, @schemaguid, @schematype, @schematext
  9969.         if @@ERROR<>0 or @retcode<>0
  9970.         begin
  9971.             select @retcode = 1
  9972.             GOTO FAILURE
  9973.         end
  9974.         raiserror(21354, 10, -1, @hub_pubname)
  9975.         exec @retcode=sp_MSBumpupCompLevel @hub_pubid, 40 
  9976.         if @@ERROR<>0 or @retcode<>0        
  9977.             GOTO FAILURE
  9978.  
  9979.         update sysmergepublications set snapshot_ready=2 where pubid=@hub_pubid
  9980.         if @@ERROR<>0
  9981.             goto FAILURE
  9982.         fetch next from reinit_hub into @hub_pubid, @hub_pubname, @hub_publisher, @hub_publisher_db
  9983.     end
  9984.     close reinit_hub
  9985.     deallocate reinit_hub
  9986.     COMMIT TRAN
  9987.     return (0)
  9988. FAILURE:
  9989.     close reinit_hub
  9990.     deallocate reinit_hub
  9991.     raiserror('Error occurred when applying reinit-all command at subscribers', 16, -1)
  9992.     if @@TRANCOUNT >0 
  9993.     begin
  9994.         ROLLBACK TRANSACTION reinithub
  9995.         COMMIT TRAN
  9996.     end
  9997.     return (0)
  9998. GO
  9999.  
  10000. exec dbo.sp_MS_marksystemobject sp_MSreinit_hub
  10001. go  
  10002.  
  10003. grant execute on dbo.sp_MSreinit_hub to public
  10004. go
  10005.  
  10006. raiserror('Creating procedure sp_reinitmergesubscription', 0, 1)
  10007. GO
  10008.  
  10009. create procedure sp_reinitmergesubscription
  10010.     @publication    sysname  = 'all',
  10011.     @subscriber     sysname  = 'all',
  10012.     @subscriber_db  sysname  = 'all',
  10013.     @upload_first    nvarchar(5) = 'FALSE'
  10014. AS
  10015.     declare @pubid                  uniqueidentifier
  10016.     declare @subid                  uniqueidentifier
  10017.     declare @subscription_type        int
  10018.     declare @reinit_bit                int
  10019.     declare @publisher                sysname
  10020.     declare @publisher_db            sysname
  10021.     declare @distribdb                sysname
  10022.     declare @distributor            sysname
  10023.     declare @distproc                nvarchar(300)
  10024.     declare @retcode                int
  10025.     declare @uploadbit                bit
  10026.     declare    @pubname                sysname
  10027.     declare @subsrvid                int
  10028.     declare @subdb                    sysname 
  10029.     declare @subname                sysname
  10030.     /* 
  10031.     ** Security Check.
  10032.     ** We use login_name stored in syssubscriptions to manage security 
  10033.     */
  10034.     exec @retcode = dbo.sp_MSreplcheck_publish
  10035.     if @@ERROR <> 0 or @retcode <> 0
  10036.         return(1)
  10037.  
  10038.     set nocount on
  10039.     /*
  10040.     ** Replace 'all' with '%'
  10041.     */
  10042.  
  10043.     /* make sure current database is enabled for merge replication */
  10044.     exec @retcode=dbo.sp_MSCheckmergereplication
  10045.     if @@ERROR<>0 or @retcode<>0
  10046.         return (1)
  10047.  
  10048.     if LOWER(@publication) = 'all'
  10049.         SELECT @publication = '%'
  10050.  
  10051.     if LOWER(@subscriber) = 'all'
  10052.         SELECT @subscriber = '%'
  10053.  
  10054.     if LOWER(@subscriber_db) = 'all'
  10055.         SELECT @subscriber_db = '%'
  10056.  
  10057.     select @publisher = @@SERVERNAME
  10058.     select @publisher_db=db_name()
  10059.     
  10060.     /*
  10061.     ** At publisher side, publication name is unique
  10062.     */
  10063.     IF NOT EXISTS (SELECT * FROM sysmergepublications 
  10064.         WHERE name LIKE @publication)
  10065.         BEGIN
  10066.         IF @publication = '%'
  10067.                 RAISERROR (14008, 11, -1)
  10068.         ELSE
  10069.                 RAISERROR (20026, 11, -1, @publication)
  10070.         RETURN (1)
  10071.         END
  10072.  
  10073.     /* if snapshot has not been ran yet, there is no point doing reinitialization */
  10074.     if not exists (select * from sysmergepublications where name like @publication and snapshot_ready>0)
  10075.         return (0)
  10076.         
  10077.     if LOWER(@upload_first collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  10078.         select @uploadbit  = 1
  10079.     else
  10080.         select @uploadbit  = 0
  10081.  
  10082.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  10083.         IF @@ERROR <> 0 or @retcode <> 0
  10084.                 return (1)
  10085.  
  10086.     SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSrefresh_anonymous '
  10087.  
  10088.     if @subscriber = '%' and @subscriber_db = '%'
  10089.     begin
  10090.         exec @retcode = @distproc @publication, @publisher, @publisher_db 
  10091.         if @@ERROR<>0 or @retcode<>0
  10092.                 return (1)
  10093.                 
  10094.         declare reinit_all CURSOR LOCAL FAST_FORWARD FOR 
  10095.             select name from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and 
  10096.                 publisher_db=db_name() and snapshot_ready>0 and name like @publication
  10097.         For READ only
  10098.         open reinit_all
  10099.         fetch reinit_all into @pubname
  10100.         while (@@fetch_status<>-1)
  10101.         begin
  10102.             exec @retcode = sp_MSreinitmergepublication @pubname, @uploadbit
  10103.             if @@ERROR<>0 or @retcode<>0
  10104.             begin
  10105.                 close reinit_all
  10106.                 deallocate reinit_all
  10107.                 return (1)
  10108.             end
  10109.             
  10110.             fetch next from reinit_all into @pubname
  10111.         end
  10112.         close reinit_all
  10113.         deallocate reinit_all
  10114.     end
  10115.  
  10116.     SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSmarkreinit '
  10117.  
  10118.     BEGIN TRAN
  10119.     SAVE TRAN reinitsubscription
  10120.     
  10121.     Declare SYN_CUR CURSOR LOCAL FAST_FORWARD FOR 
  10122.         select subs.subid, subs.subscription_type, pubs.publisher, pubs.publisher_db, pubs.name, 
  10123.                 subs.srvid, subs.db_name
  10124.             from sysmergepublications pubs, sysmergesubscriptions subs
  10125.                 where pubs.name LIKE  @publication 
  10126.                      and UPPER(pubs.publisher)=UPPER(@@servername) 
  10127.                      and pubs.publisher_db=db_name()
  10128.                     AND pubs.pubid=subs.pubid
  10129.                     AND subs.pubid<>subs.subid
  10130.                     AND subs.status <>0 --for unsynced subscription, there is no need to reinit.
  10131.                     AND ((@subscriber_db = N'%') or (db_name = @subscriber_db))
  10132.                     AND srvid in (select srvid from master..sysservers where ((@subscriber = N'%') or (UPPER(srvname) = UPPER(@subscriber) collate database_default)))
  10133.     FOR READ ONLY
  10134.     open SYN_CUR
  10135.     fetch SYN_CUR into @subid, @subscription_type, @publisher, @publisher_db, @pubname, @subsrvid, @subdb
  10136.     while (@@fetch_status<>-1)
  10137.     BEGIN  
  10138.     -- Security check 
  10139.         if not exists (select * from sysmergesubscriptions subs1 where
  10140.         (suser_sname(suser_sid()) = subs1.login_name OR 
  10141.         is_member('db_owner')=1 OR 
  10142.         is_srvrolemember('sysadmin') = 1) and
  10143.         subid = @subid)
  10144.         continue        
  10145.  
  10146.         select @subname = srvname from master..sysservers where srvid = @subsrvid
  10147.     
  10148.             if @subscription_type = 0 
  10149.                  update MSmerge_replinfo set schemaversion=0, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
  10150.                       where repid=@subid and schemaversion is NOT NULL
  10151.             else
  10152.                     update MSmerge_replinfo set schemaversion= -1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL
  10153.                        where repid=@subid and schemaversion is NOT NULL
  10154.         
  10155.         if @@rowcount <> 0 and @uploadbit = 1
  10156.         begin
  10157.             update sysmergesubscriptions set status = 5 where subid=@subid
  10158.             if @@ERROR<>0
  10159.                 goto Failure
  10160.         end
  10161.  
  10162.         -- If subscriber was preventing us from cleaning up metadata, set the status
  10163.         update sysmergesubscriptions set status = 8 where subid = @subid and status = 7
  10164.         if @@rowcount <> 0
  10165.             exec sp_MSquiescecheck
  10166.             
  10167.         -- 0 for push and -1 for pull
  10168.         exec @distproc @publisher, @publisher_db, @pubname, @subname, @subdb, 1
  10169.         if @@ERROR<>0
  10170.         BEGIN
  10171.             goto Failure
  10172.         END            
  10173.         fetch next from SYN_CUR into @subid, @subscription_type, @publisher, 
  10174.             @publisher_db, @pubname, @subsrvid, @subdb        
  10175.     END
  10176.     close SYN_CUR
  10177.     deallocate SYN_CUR
  10178.     commit TRAN
  10179.     return (0)
  10180. Failure:
  10181.     close SYN_CUR
  10182.     deallocate SYN_CUR
  10183.     if @@TRANCOUNT > 0
  10184.     begin
  10185.         ROLLBACK TRANSACTION reinitsubscription
  10186.         COMMIT TRANSACTION
  10187.     end
  10188.     return (1)
  10189.  
  10190. GO
  10191.  
  10192. exec dbo.sp_MS_marksystemobject sp_reinitmergesubscription
  10193. go  
  10194.  
  10195. grant execute on dbo.sp_reinitmergesubscription to public
  10196. go
  10197.  
  10198. raiserror('Creating procedure sp_MSpublicationview', 0,1)
  10199. GO
  10200.  
  10201. CREATE PROCEDURE sp_MSpublicationview(
  10202.     @publication sysname,
  10203.     @force_flag int = 0,
  10204.     @max_network_optimization bit = 0
  10205.     ) AS
  10206.     declare     @pubid              uniqueidentifier
  10207.     declare     @artid              uniqueidentifier
  10208.     declare     @join_articlename       nvarchar(270)
  10209.     declare     @join_viewname      nvarchar(270)
  10210.     declare     @join_before_view      nvarchar(270)
  10211.     declare        @before_name        nvarchar(270)
  10212.     declare        @before_viewname    nvarchar(270)
  10213.     declare     @unqual_sourcename    nvarchar(270)
  10214.     declare     @article            nvarchar(270)
  10215.     declare     @art_nick           int
  10216.     declare     @join_nick          int
  10217.     declare     @join_filterclause  nvarchar(4000)
  10218.     declare     @bool_filterclause  nvarchar(4000)
  10219.     declare     @view_rule          nvarchar(4000)
  10220.     declare        @before_view_rule    nvarchar(4000)
  10221.     declare        @before_objid        int
  10222.     declare     @article_level      int
  10223.     declare     @progress           int
  10224.     declare     @art                int
  10225.     declare     @viewname           nvarchar(270)
  10226.     declare     @procname           nvarchar(300)
  10227.     declare     @source_objid       int
  10228.     declare     @source_object      nvarchar(270)
  10229.     declare     @sync_objid         int
  10230.     declare     @bitset                int
  10231.     declare     @permanent          int
  10232.     declare     @temporary          int
  10233.     declare     @filter_id          int
  10234.     declare     @filter_id_str      nvarchar(10)
  10235.     declare     @guidstr nvarchar(40)
  10236.     declare     @pubidstr nvarchar(40)
  10237.     declare     @rgcol              nvarchar(270)
  10238.     declare     @view_type          int
  10239.     declare     @belongsname        nvarchar(270)
  10240.     declare     @join_nickstr       nvarchar(10)
  10241.     declare     @unqual_jointable   nvarchar(270)  
  10242.     declare     @retcode            smallint
  10243.     declare     @hasguid            int
  10244.     declare     @vertical_partition int
  10245.     declare     @join_unique_key    int
  10246.     declare     @simple_join_view   int
  10247.     declare     @join_filterid      int
  10248.     declare     @allhaveguids       int
  10249.     declare     @command            nvarchar(4000)
  10250.     declare     @objid              int
  10251.     declare     @owner              nvarchar(270)
  10252.     declare        @table                nvarchar(270)
  10253.     declare     @quoted_view        nvarchar(290)
  10254.     declare     @before_rowguidname    sysname
  10255.     declare     @quoted_pub         nvarchar(290)
  10256.     declare     @quoted_proc        nvarchar(290)
  10257.     declare     @snapshot_ready        int
  10258.     declare     @columns            varbinary(128)
  10259.     declare        @column_list        nvarchar(4000)
  10260.     declare        @prefixed_column_list        nvarchar(4000)
  10261.     declare     @colname            nvarchar(270)
  10262.     declare     @colid                int
  10263.     declare     @dynamic_filters    bit
  10264.     declare        @alias_for_sourceobject    sysname
  10265.     set @progress       = 1
  10266.     set @article_level  = 0
  10267.     set @permanent      = 1
  10268.     set @temporary      = 2
  10269.     set @allhaveguids   = 1
  10270.     set @before_rowguidname = NULL
  10271.     /*
  10272.     ** Only legal publisher can run this stored procedure
  10273.     */
  10274.     set nocount on
  10275.     /* make sure current database is enabled for merge replication */
  10276.     exec @retcode=dbo.sp_MSCheckmergereplication
  10277.     if @@ERROR<>0 or @retcode<>0
  10278.         return (1)
  10279.  
  10280.     select @pubid = pubid, @snapshot_ready = snapshot_ready, @dynamic_filters = dynamic_filters FROM sysmergepublications 
  10281.         WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name() 
  10282.     IF @pubid IS NULL
  10283.         BEGIN
  10284.             RAISERROR (20026, 11, -1, @publication)
  10285.             RETURN (1)
  10286.         END
  10287.  
  10288.     select @table=object_name(objid) from sysmergearticles where pubid=@pubid and (columns is NULL or columns = 0x00)
  10289.     if @table is not NULL
  10290.         begin
  10291.             raiserror(21318, 16, -1, @table)
  10292.             return (1)
  10293.         end
  10294.  
  10295.     -- If snapshot is already ready, views are good.  Don't drop and recreate as someone
  10296.     -- might be using them.
  10297.     
  10298.     if @snapshot_ready = 1 and @force_flag = 0
  10299.         return (0)
  10300.         
  10301.     exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  10302.     if @@ERROR <>0 OR @retcode <>0 return (1)
  10303.  
  10304.     create table #art(indexcol int identity NOT NULL, art_nick int NOT NULL, article_level int NOT NULL)
  10305.     if @@ERROR <> 0
  10306.         begin
  10307.         goto FAILURE
  10308.         end
  10309.  
  10310.     while @progress > 0
  10311.         BEGIN
  10312.         /*
  10313.         ** Select articles that have either a boolean_filter or at least one join filter 
  10314.         ** into a temp table in an optimized order.
  10315.         */
  10316.         insert into #art(art_nick, article_level) select nickname, @article_level from sysmergearticles 
  10317.             where pubid=@pubid and nickname not in (select art_nick from #art)
  10318.                 and nickname not in 
  10319.                 (select  art_nickname from sysmergesubsetfilters
  10320.                     where pubid=@pubid and join_nickname not in 
  10321.                         (select art_nick from #art))
  10322.         /*
  10323.         ** NOTENOTE: add error checking here.
  10324.         */
  10325.  
  10326.         set @progress = @@rowcount
  10327.         select @article_level = @article_level + 1
  10328.         END
  10329.  
  10330.     /* Drop the old views and reset sync_objid */
  10331.     select @art_nick = min(nickname) from sysmergearticles where pubid = @pubid and objid<>sync_objid
  10332.     while @art_nick is not null
  10333.         begin
  10334.         /* Drop the old view */
  10335.         select @viewname = OBJECT_NAME (sync_objid), @before_viewname = OBJECT_NAME(before_view_objid)
  10336.             from sysmergearticles where
  10337.             pubid = @pubid and nickname = @art_nick
  10338.         if @viewname IS NOT NULL
  10339.         begin
  10340.             select @quoted_view = QUOTENAME(@viewname)
  10341.             exec ('drop view ' + @quoted_view)
  10342.         end
  10343.         if @before_viewname IS NOT NULL
  10344.         begin
  10345.             exec ('drop view ' + @before_viewname)
  10346.         end
  10347.         /* Update the row in sysmergearticles */
  10348.         update sysmergearticles set view_type = 0, sync_objid = objid where 
  10349.             pubid = @pubid and nickname = @art_nick
  10350.         if @@ERROR <> 0 goto FAILURE
  10351.  
  10352.         /* Find the next one */
  10353.         select @art_nick = min(nickname) from sysmergearticles where pubid = @pubid and objid<>sync_objid
  10354.         end
  10355.         
  10356.     set @art = 0
  10357.     select @art=min(indexcol) from #art where indexcol>@art
  10358.  
  10359.     while (@art is not null)
  10360.         begin
  10361.         select @art_nick=art_nick, @article_level = article_level from #art 
  10362.                 where indexcol = @art
  10363.         select @article = name, @artid = artid, @columns = columns, @source_objid = objid,
  10364.             @sync_objid = sync_objid, @procname = view_sel_proc, @before_objid = before_image_objid from sysmergearticles 
  10365.                 where nickname=@art_nick and pubid = @pubid
  10366.                 
  10367.         exec @retcode = sp_MSgetcolumnlist @pubid, @column_list OUTPUT, @source_objid
  10368.         
  10369.         set @before_name = OBJECT_NAME(@before_objid)
  10370.         if @before_name is not null
  10371.             begin
  10372.             select @before_rowguidname=name from syscolumns where id=@source_objid and columnproperty(@source_objid, name , 'isrowguidcol')=1
  10373.             exec @retcode = dbo.sp_MSguidtostr @pubid, @guidstr out
  10374.             set @before_viewname = @before_name + '_v_' + @guidstr
  10375.             end
  10376.         else
  10377.             set @before_viewname = NULL
  10378.         select @quoted_proc = QUOTENAME(@procname)
  10379.         
  10380.         exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
  10381.         if @@ERROR <>0 OR @retcode <>0 return (1)
  10382.  
  10383.         select @source_object = QUOTENAME(user_name(uid)) + '.' + QUOTENAME(name) from sysobjects 
  10384.                 where id = @source_objid 
  10385.         select @unqual_sourcename = QUOTENAME(OBJECT_NAME(@source_objid))
  10386.         
  10387.         select @bool_filterclause=subset_filterclause, @vertical_partition=vertical_partition 
  10388.             from sysmergearticles where name = @article and pubid = @pubid
  10389.  
  10390.         -- verify the syntax of boolean filter, if added with vertical-partition to true
  10391.         -- in this case, the filter clause can contain columns that do not exist in the partition.
  10392.         if len(@bool_filterclause) > 0
  10393.             begin
  10394.             /*
  10395.             -- let server return appropriate error message 
  10396.             exec ('select ' + @column_list + ' into #temptable_publicationview from ' + @source_object + 
  10397.                 'declare @test int select @test=1 from #temptable_publicationview ' + @unqual_sourcename + ' where ' + @bool_filterclause)
  10398.             if @@ERROR<>0
  10399.             begin
  10400.                 raiserror(21256, 16, -1, @bool_filterclause, @source_object)
  10401.                 return (1)
  10402.             end
  10403.             */
  10404.             select @bool_filterclause = ' (' + @bool_filterclause + ') '
  10405.             end
  10406.                 
  10407.         set @rgcol = NULL
  10408.         select @rgcol = QUOTENAME(name) from syscolumns where id = @source_objid and
  10409.                 ColumnProperty(id, name, 'isrowguidcol') = 1
  10410.         if @rgcol is not NULL
  10411.             set @hasguid = 1
  10412.         else 
  10413.             begin
  10414.             set @hasguid = 0
  10415.             set @allhaveguids = 0
  10416.             end
  10417.  
  10418.         /*
  10419.         ** Process non looping articles that have either a boolean or a join_filter.
  10420.         */
  10421.         if ( @article_level > 0 OR (len(@bool_filterclause) > 0) ) 
  10422.             begin
  10423.             /*
  10424.             ** If the article has a previously generated view, then drop the view before 
  10425.             ** creating the new one.
  10426.             */
  10427.             set @viewname = NULL
  10428.             select @viewname =  name from sysobjects where id = @sync_objid and
  10429.                 ObjectProperty (id, 'IsView') = 1  and
  10430.                 ObjectProperty (id, 'IsMSShipped') = 1 
  10431.             if @viewname IS NOT NULL
  10432.                 begin
  10433.                     select @quoted_view = QUOTENAME(@viewname)
  10434.                     exec ('drop view ' + @quoted_view)
  10435.                     if @@ERROR<>0 return (1)
  10436.                 end
  10437.                 /*
  10438.                 ** Any join filter(s)? If any, process join filter(s)
  10439.                 */
  10440.             if (@article_level > 0) 
  10441.                 begin
  10442.                 declare pub1 CURSOR LOCAL FAST_FORWARD FOR select join_filterclause, join_nickname, join_articlename,
  10443.                     join_unique_key, join_filterid from sysmergesubsetfilters where pubid=@pubid and artid=@artid
  10444.                 FOR READ ONLY
  10445.                 open pub1                                       
  10446.                 fetch pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid
  10447.                 select @join_filterclause=' ( ' + @join_filterclause + ') '
  10448.                 select @unqual_jointable = QUOTENAME(name) from sysobjects 
  10449.                     where id = (select objid from sysmergearticles where name=@join_articlename and pubid=@pubid) 
  10450.                 
  10451.                 if @max_network_optimization = 0
  10452.                     select @join_viewname = object_name(sync_objid), @join_before_view = object_name(before_image_objid)
  10453.                     from sysmergearticles where nickname = @join_nick and pubid = @pubid
  10454.                 else
  10455.                     select @join_viewname = object_name(sync_objid), 
  10456.                     @join_before_view = object_name(case when before_view_objid is not null then before_view_objid else before_image_objid end)
  10457.                     from sysmergearticles where nickname = @join_nick and pubid = @pubid
  10458.                     
  10459.                 select @join_viewname = QUOTENAME(@join_viewname)
  10460.  
  10461.                 if (@join_unique_key = 1 and (@bool_filterclause is null or len(@bool_filterclause) = 0) and
  10462.                     not exists (select * from sysmergesubsetfilters where pubid=@pubid and artid=@artid and join_filterid <> @join_filterid))
  10463.                     begin
  10464.                     set @simple_join_view = 1
  10465.                     if @column_list = ' * '
  10466.                         select @column_list = ' ' + @unqual_sourcename + '.* '
  10467.                     set @view_rule = 'select ' + @column_list + ' from ' + @source_object + ' ' + @unqual_sourcename + ' , ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
  10468.                     /* add security check to the view if this is a dynamically filtered publication */
  10469.                     set @view_rule = @view_rule + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  10470.                     end
  10471.                 else
  10472.                     begin
  10473.                     set @simple_join_view = 0
  10474.                     /* Alias the source object with the unqualified name and use that to select the rowguidcol */                   
  10475.                     set @view_rule = 'select ' + @unqual_sourcename + '.rowguidcol from ' + @source_object  + ' ' + @unqual_sourcename + ' , ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
  10476.                     end
  10477.                 if @before_name is not null
  10478.                     set @before_view_rule = 'select * from ' + @before_name + ' ' +  @unqual_sourcename + ' where exists (select * from ' +
  10479.                             @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') or exists (select * from ' +
  10480.                             @join_before_view + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') '
  10481.                             
  10482.                 fetch next from pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid
  10483.                 WHILE (@@fetch_status <> -1)
  10484.                     begin
  10485.                     select @join_filterclause=' ( ' + @join_filterclause + ') '
  10486.                     select @unqual_jointable = name from sysobjects 
  10487.                         where id = ( select objid from sysmergearticles where name=@join_articlename and pubid=@pubid) 
  10488.        
  10489.                     if @max_network_optimization = 0
  10490.                         select @join_viewname = object_name(sync_objid), @join_before_view = object_name(before_image_objid)
  10491.                         from sysmergearticles where nickname = @join_nick and pubid = @pubid
  10492.                     else
  10493.                         select @join_viewname = object_name(sync_objid), 
  10494.                            @join_before_view = object_name(case when before_view_objid is not null then before_view_objid else before_image_objid end)
  10495.                         from sysmergearticles where nickname = @join_nick and pubid = @pubid
  10496.                     
  10497.                     select @join_viewname = QUOTENAME(@join_viewname)
  10498.                     set @view_rule = @view_rule + ' union select ' + @source_object + '.rowguidcol from ' + @source_object + ', ' +  @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause
  10499.                        if @before_name is not null
  10500.                         set @before_view_rule = @before_view_rule + ' or exists (select * from ' +
  10501.                             @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') or exists (select * from ' +
  10502.                             @join_before_view + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') '
  10503.                  
  10504.                     fetch next from pub1 into @join_filterclause, @join_nick, @join_articlename, @join_unique_key, @join_filterid
  10505.                     end 
  10506.                 close pub1
  10507.                 deallocate pub1
  10508.                         
  10509.                 if len(@bool_filterclause) > 0
  10510.                     begin
  10511.                     set @view_rule = @view_rule + ' union select ' + @source_object + '.rowguidcol from '+ @source_object + ' where '+ @bool_filterclause
  10512.                        if @before_name is not null
  10513.                         set @before_view_rule = @before_view_rule + ' or ' + @bool_filterclause
  10514.                     
  10515.                     end
  10516.                 -- Now do the actual view rule as a semi-join, if not a simple join on unique key
  10517.                 if (@simple_join_view = 0)
  10518.                     begin
  10519.                     /* 
  10520.                     ** Generate a unique alias for the outer select to make sure that it does not generate an
  10521.                     ** ambiguous reference with table names used in the join_filter clause 
  10522.                     */
  10523.                     set @alias_for_sourceobject = 'alias_' + @guidstr
  10524.                     exec @retcode = sp_MSgetcolumnlist @pubid, @prefixed_column_list OUTPUT, @source_objid, @alias_for_sourceobject
  10525.  
  10526.                     set @view_rule = 'select ' + @prefixed_column_list + ' from ' + @source_object + ' ' + @alias_for_sourceobject + ' where rowguidcol in (' + @view_rule + ')'
  10527.                     set @view_rule = @view_rule + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  10528.                     end
  10529.                 end
  10530.             else  /* boolean filter only */
  10531.                 begin
  10532.                 select @view_rule = ' select ' + @column_list + ' from '+ @source_object + ' ' + @unqual_sourcename + ' where '+ @bool_filterclause
  10533.                 if @before_name is not null
  10534.                     set @before_view_rule = ' select * from ' + @before_name + ' ' + @unqual_sourcename + ' where ' + @bool_filterclause
  10535.                 set @view_rule = @view_rule + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  10536.                 end
  10537.                            
  10538.             select @viewname = @publication + '_' + @article + '_VIEW'
  10539.             exec @retcode = dbo.sp_MSuniqueobjectname @viewname , @viewname output
  10540.             select @quoted_view = QUOTENAME(@viewname)
  10541.             
  10542.             if @retcode <> 0 or @@ERROR <> 0 return (1) 
  10543.             /* If we havent generated rowguidcol yet, use dummy rule that doesnt refer to it */
  10544.             if @hasguid = 0
  10545.                 set @view_rule = ' select ' + @column_list + ' from '+ @source_object + ' ' + @unqual_sourcename
  10546.             exec ('create view '+ @quoted_view + ' as '+ @view_rule)
  10547.             if @@ERROR<>0
  10548.                 return (1)
  10549.             /* grant select permission on sync view to public - security check is performed inside the view */ 
  10550.             exec ('grant select on ' + @quoted_view + ' to public')
  10551.             if @@ERROR<>0
  10552.                 return (1)
  10553.             /* Mark view as system object */                        
  10554.             execute sp_MS_marksystemobject @quoted_view
  10555.             if @@ERROR<>0
  10556.                 return (1)
  10557.             if @hasguid = 1
  10558.                 begin
  10559.                 select @procname=view_sel_proc from sysmergearticles where pubid=@pubid and artid=@artid
  10560.                 if object_id(@procname) is not NULL
  10561.                     begin
  10562.                     exec ('drop procedure ' + @quoted_proc)
  10563.                     update sysmergearticles set view_sel_proc = NULL where artid = @artid and pubid = @pubid 
  10564.                     end
  10565.                 else
  10566.                     begin
  10567.                     set @procname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  10568.                     exec @retcode = dbo.sp_MSuniqueobjectname @procname , @procname output
  10569.                     if @retcode <> 0 or @@ERROR <> 0
  10570.                             return (1)
  10571.                     end
  10572.                 select @owner = user_name(uid) from sysobjects 
  10573.                     where name = @viewname 
  10574.                 exec dbo.sp_MSmakeviewproc @viewname, @owner, @procname, @rgcol, @source_objid
  10575.                 if @retcode<>0 or @@ERROR<>0
  10576.                     return (1)
  10577.                 update sysmergearticles set view_sel_proc = @procname where pubid=@pubid and artid=@artid
  10578.                 end
  10579.             select @quoted_view = QUOTENAME(@viewname)
  10580.             update sysmergearticles set sync_objid = OBJECT_ID (@quoted_view), view_type = @permanent
  10581.                 where artid = @artid and pubid = @pubid 
  10582.             if @before_name is not null and @before_view_rule is not null
  10583.                 begin
  10584.                 exec @retcode = sp_MScreatebeforetable @source_objid
  10585.                 if @@ERROR <>0 OR @retcode <>0 return (1)
  10586.                 if object_id(@before_viewname) is not NULL
  10587.                     exec ('drop view ' + @before_viewname)                
  10588.                 exec ('create view ' + @before_viewname + ' as ' + @before_view_rule)
  10589.                 if @@ERROR<>0
  10590.                     return (1)
  10591.                 if @before_rowguidname is not NULL
  10592.                     begin
  10593.                         exec ('grant select (' + @before_rowguidname + ') on '+ @before_viewname + ' to public')
  10594.                         if @@ERROR<>0
  10595.                             return (1)
  10596.                     end
  10597.  
  10598.                 exec ('grant select (generation) on '+ @before_viewname + ' to public')
  10599.                 if @@ERROR<>0
  10600.                     return (1)
  10601.  
  10602.                 execute sp_MS_marksystemobject @before_viewname
  10603.                 if @@ERROR<>0
  10604.                     return (1)
  10605.                 update sysmergearticles set before_view_objid = OBJECT_ID (@before_viewname)
  10606.                     where artid = @artid and pubid = @pubid
  10607.                 end
  10608.  
  10609.             end /* end of view creation for this article */
  10610.         else 
  10611.         begin
  10612.             select @sync_objid = @source_objid
  10613.             if @vertical_partition=1 and @column_list<> ' * '
  10614.                 begin
  10615.                     select @viewname = @publication + '_' + @article + '_VIEW'
  10616.                     exec @retcode = dbo.sp_MSuniqueobjectname @viewname , @viewname output
  10617.                     select @quoted_view = QUOTENAME(@viewname)
  10618.                     set @view_rule = ' select ' + @column_list + ' from '+ @source_object + ' ' + @unqual_sourcename
  10619.                     set @view_rule = @view_rule + ' where ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  10620.  
  10621.                     exec ('create view '+ @quoted_view + ' as '+ @view_rule)
  10622.                     if @@ERROR<>0
  10623.                         return (1)
  10624.                     execute sp_MS_marksystemobject @quoted_view
  10625.                     if @@ERROR<>0
  10626.                         return (1)
  10627.  
  10628.                     /* grant select permission on sync view to public - security check is performed inside the view */ 
  10629.                     exec ('grant select on ' + @quoted_view + ' to public')
  10630.                     if @@ERROR<>0
  10631.                         return (1)
  10632.                     select @sync_objid=object_id(@viewname)
  10633.                 update sysmergearticles set view_sel_proc = @procname, sync_objid=@sync_objid
  10634.                     where artid = @artid and pubid = @pubid 
  10635.                 end
  10636.             else if @dynamic_filters = 1
  10637.                 begin
  10638.                     /* This article doesn't have any vertical or horizontal filters but if the publication is enabled for dynamic filtering, 
  10639.                         we still want to generate a dummy view so that logins in the publication access list can generate a dynamic snapshot. */
  10640.                     select @viewname = @publication + '_' + @article + '_VIEW'
  10641.                     exec @retcode = dbo.sp_MSuniqueobjectname @viewname, @viewname output
  10642.                     select @quoted_view = QUOTENAME(@viewname)
  10643.                     set @view_rule = ' select  * from ' + @source_object  + ' where ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'     
  10644.                     exec ('create view '+ @quoted_view + ' as '+ @view_rule)
  10645.                     if @@ERROR<>0
  10646.                         return (1)
  10647.                     execute sp_MS_marksystemobject @quoted_view
  10648.                     if @@ERROR<>0
  10649.                         return (1)
  10650.                     exec ('grant select on ' + @quoted_view + ' to public')
  10651.                     if @@ERROR<>0
  10652.                         return (1)
  10653.                     select @sync_objid=object_id(@viewname)
  10654.                     update sysmergearticles set view_sel_proc = @procname, sync_objid=@sync_objid, view_type = @permanent
  10655.                     where artid = @artid and pubid = @pubid 
  10656.                 end
  10657.  
  10658.             if @hasguid = 1
  10659.             begin
  10660.             /* still make the select proc, although it selects directly from table */
  10661.             if object_id(@procname) is not NULL
  10662.                 begin
  10663.                     exec ('drop proc ' + @procname)
  10664.                     update sysmergearticles set view_sel_proc = NULL where artid = @artid and pubid = @pubid 
  10665.                 end
  10666.             set @procname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  10667.             exec @retcode = dbo.sp_MSuniqueobjectname @procname , @procname output
  10668.             if @retcode <> 0 or @@ERROR <> 0 return (1) 
  10669.             select @owner = user_name(uid), @viewname = name from sysobjects 
  10670.                 where id = @source_objid
  10671.             exec dbo.sp_MSmakeviewproc @viewname, @owner, @procname, @rgcol, @source_objid
  10672.             update sysmergearticles set view_sel_proc = @procname where pubid=@pubid and artid=@artid
  10673.             end
  10674.         end
  10675.    select @art=min(indexcol) from #art where indexcol>@art
  10676.    end
  10677.  
  10678.     /* If there are looping articles, we must use a dynamic publication since no views on temp tables */
  10679.     update sysmergearticles set view_type = @temporary
  10680.         where pubid=@pubid and nickname not in (select art_nick from #art)
  10681.     if @@rowcount > 0
  10682.         begin
  10683.         if not exists (select * from sysmergepublications where dynamic_filters = 1 and pubid = @pubid)
  10684.             begin
  10685.             declare @repl_nick int
  10686.             /* treat these articles as if the publication were dynamic */
  10687.             execute @retcode = dbo.sp_MSgetreplnick @nickname = @repl_nick output
  10688.             if (@@error <> 0) or @retcode <> 0 or @repl_nick IS NULL 
  10689.                 begin
  10690.                 RAISERROR (14055, 11, -1)
  10691.                 RETURN(1)
  10692.                 end                 
  10693.  
  10694.             select @art_nick = min(nickname) from sysmergearticles where
  10695.                 pubid = @pubid and view_type = @temporary
  10696.             while @art_nick is not null
  10697.                 begin
  10698.                 /* Loop over articles with circular filters.  Create dummy view and add rows to contents */
  10699.                 select @article = name, @artid = artid, @source_objid = objid, @sync_objid = sync_objid, @procname = view_sel_proc from sysmergearticles 
  10700.                     where nickname=@art_nick and pubid = @pubid
  10701.                 select @source_object = QUOTENAME(user_name(uid)) + '.' + QUOTENAME(name) from sysobjects 
  10702.                     where id = @source_objid 
  10703.  
  10704.                 set @viewname = NULL
  10705.                 select @viewname =  name from sysobjects where id = @sync_objid and
  10706.                     ObjectProperty (id, 'IsView') = 1  and
  10707.                     ObjectProperty (id, 'IsMSShipped') = 1 
  10708.                 if @viewname IS NOT NULL
  10709.                     begin
  10710.                         select @quoted_view = QUOTENAME(@viewname)
  10711.                         exec ('drop view ' + @quoted_view)
  10712.                         if @@ERROR<>0 return (1)
  10713.                     end
  10714.                 select @viewname = 'SYNC_' + @publication + '_' + @article 
  10715.                 exec @retcode = dbo.sp_MSuniqueobjectname @viewname , @viewname output
  10716.                 if @retcode <> 0 or @@ERROR <> 0 return (1) 
  10717.                 select @quoted_view = QUOTENAME(@viewname)
  10718.                 exec ('create view ' + @quoted_view + ' as select * from ' + @source_object + ' 
  10719.                         where 1 = 0 ')
  10720.                 if @@ERROR<>0 return (1)
  10721.                 update sysmergearticles set sync_objid = OBJECT_ID (@viewname),
  10722.                     view_sel_proc = NULL where artid = @artid and pubid = @pubid 
  10723.                 if @@ERROR<>0 return (1)
  10724.  
  10725.                 select @owner = user_name(uid) from sysobjects where id = @source_objid
  10726.                 set @table = OBJECT_NAME(@source_objid)
  10727.                 exec @retcode = dbo.sp_addtabletocontents @table, @owner
  10728.                 IF @@ERROR <> 0 or @retcode <> 0 return (1)
  10729.                 
  10730.                 select @art_nick = min(nickname) from sysmergearticles where
  10731.                     pubid = @pubid and view_type = @temporary and nickname > @art_nick
  10732.                 end
  10733.             end
  10734.         end
  10735.         
  10736.     drop table #art
  10737.     if @allhaveguids = 1
  10738.         begin
  10739.         declare @dbname sysname
  10740.         set @dbname = db_name()
  10741.         /* create the filter expand procs now */
  10742.         set @filter_id = 0
  10743.         select @filter_id = min(join_filterid) from sysmergesubsetfilters where
  10744.                 pubid = @pubid and join_filterid > @filter_id
  10745.         while @filter_id is not null
  10746.             begin
  10747.             set @filter_id_str = convert(nvarchar(10), @filter_id)
  10748.             select @procname = expand_proc
  10749.                 from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filter_id
  10750.             /* drop old proc, or generate a new procname */
  10751.             select @quoted_proc = QUOTENAME(@procname)
  10752.             if object_id(@procname) is not NULL
  10753.                 exec ('drop procedure ' + @quoted_proc)
  10754.             else
  10755.                 begin
  10756.                 set @procname = 'expand_' + @filter_id_str
  10757.                 exec @retcode = dbo.sp_MSuniqueobjectname @procname, @procname output
  10758.                 if @retcode <>0 return (1)
  10759.                 update sysmergesubsetfilters set expand_proc = @procname where  pubid = @pubid and join_filterid = @filter_id
  10760.                 end
  10761.             select @quoted_proc = QUOTENAME(@procname)
  10762.             select @quoted_pub = QUOTENAME(@publication)
  10763.             set @command = 'exec dbo.sp_MSmakeexpandproc ' + @quoted_pub + ' , ' + @filter_id_str + ', ' + @quoted_proc
  10764.             exec @retcode = master..xp_execresultset @command, @dbname
  10765.             if @retcode <> 0 return (1)
  10766.             exec dbo.sp_MS_marksystemobject @quoted_proc
  10767.             if @@ERROR<>0
  10768.                 return (1)
  10769.             exec ('grant execute on ' + @quoted_proc + ' to public ')
  10770.             select @filter_id = min(join_filterid) from sysmergesubsetfilters where
  10771.                 pubid = @pubid and join_filterid > @filter_id
  10772.             end
  10773.         end
  10774.  
  10775.     return (0)
  10776.  
  10777. FAILURE: 
  10778.     return (1)
  10779. go
  10780.  
  10781. exec dbo.sp_MS_marksystemobject sp_MSpublicationview
  10782. go
  10783.  
  10784. grant execute on dbo.sp_MSpublicationview to public
  10785. go
  10786.  
  10787. dump tran master with no_log
  10788. go
  10789.  
  10790. raiserror('Creating procedure sp_addmergesubscription', 0,1)
  10791. GO
  10792. CREATE PROCEDURE sp_addmergesubscription (
  10793.     @publication                    sysname,                    /* Publication name */
  10794.     @subscriber                     sysname = NULL,             /* Subscriber server */
  10795.     @subscriber_db                  sysname = NULL,             /* Subscription database */
  10796.     @subscription_type              nvarchar(15) = 'push',          /* Subscription type - push, pull */ 
  10797.     @subscriber_type                nvarchar(15) = 'local',         /* Subscriber type */ 
  10798.     @subscription_priority          real        = NULL,             /* Subscription priority */
  10799.     @sync_type                      nvarchar(15) = 'automatic',     /* subscription sync type */
  10800.     @frequency_type                 int = NULL,            
  10801.     @frequency_interval             int = NULL,        
  10802.     @frequency_relative_interval    int = NULL,
  10803.     @frequency_recurrence_factor    int = NULL,
  10804.     @frequency_subday               int = NULL,            
  10805.     @frequency_subday_interval      int = NULL,
  10806.     @active_start_time_of_day       int = NULL,
  10807.     @active_end_time_of_day         int = NULL,
  10808.     @active_start_date              int = NULL,
  10809.     @active_end_date                int = NULL,
  10810.     @optional_command_line          nvarchar(4000) = NULL,
  10811.     @description                    nvarchar(255) = NULL,
  10812.     @enabled_for_syncmgr            nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */
  10813.     -- Agent offload
  10814.     @offloadagent                   bit = 0,
  10815.     @offloadserver                  sysname = NULL,
  10816.     @use_interactive_resolver        nvarchar(5) = 'false',
  10817.     @merge_job_name                    sysname = NULL
  10818.     ) AS
  10819.  
  10820.     SET NOCOUNT ON
  10821.  
  10822.     /*
  10823.     ** Declarations.
  10824.     */
  10825.     declare @retcode                int
  10826.     declare @subnickname            int
  10827.     declare @subscriber_srvid       int 
  10828.     declare @publisher_srvid        int 
  10829.     declare @priority               real
  10830.     declare @subid                  uniqueidentifier
  10831.     declare @pubid                  uniqueidentifier    /* Publication id */
  10832.     declare @subscriber_typeid      smallint
  10833.     declare @merge_jobid            binary(16)          /* Scheduler jobid for the merge agent */
  10834.     declare @subscription_type_id   int   
  10835.     declare @distproc               nvarchar(300)
  10836.     declare @command                nvarchar(255)
  10837.     declare @inactive               tinyint
  10838.     declare @subscriber_bit         smallint
  10839.     declare @global                 tinyint     /* subscriber type is global */
  10840.     declare @push                   tinyint     /* subscription type is push */
  10841.     declare @partnerid              uniqueidentifier    /* Partner replica identifier */
  10842.     declare @sync_typeid            tinyint
  10843.     declare @nosync                 tinyint     
  10844.     declare @automatic              tinyint     
  10845.     declare @distributor            sysname
  10846.     declare @distribdb              sysname
  10847.     declare @publisher              sysname
  10848.     declare @publisher_db           sysname
  10849.     declare @found                  int
  10850.     declare @datasource_type        int
  10851.     declare @datasource_path        sysname
  10852.     DECLARE @platform_nt            binary
  10853.     declare @datasrctype            int
  10854.     declare @datasrcpath            sysname
  10855.     declare @use_interactive_bit    bit
  10856.  
  10857.     
  10858.     /* make sure current database is enabled for merge replication */
  10859.     exec @retcode=dbo.sp_MSCheckmergereplication
  10860.     if @@ERROR<>0 or @retcode<>0
  10861.         return (1)
  10862.  
  10863.     /*
  10864.     ** Initializations.
  10865.     */
  10866.     set @datasource_type = 0    /* Default SQL Server */
  10867.     set @datasource_path = NULL 
  10868.     set @datasrctype = 0    /* Default SQL Server */
  10869.     set @datasrcpath = NULL 
  10870.     set @platform_nt = 0x1  
  10871.     SET @nosync             = 2       /* Const: synchronization type 'none' */
  10872.     SET @automatic          = 1       /* Const: synchronization type 'automatic' */
  10873.     set @inactive           = 0
  10874.     SET @subscriber_bit     = 4  
  10875.     set @global             = 1
  10876.     set @push               = 0
  10877.     set @pubid              = NULL         
  10878.     set @publisher          = @@SERVERNAME
  10879.     set @publisher_db       = DB_NAME()
  10880.     select @found           = 1    /* Any non-NULL value is fine */
  10881.     /*
  10882.     ** Parameter Check: @subscription_type.
  10883.     ** Set subscriber_typeid based on the @subscription_type specified.
  10884.     **
  10885.     **   subscription_type    subscription_type
  10886.     **   =================    ===============
  10887.     **             0            push
  10888.     **             1            pull
  10889.     */
  10890.     if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('push', 'pull')
  10891.         BEGIN
  10892.             RAISERROR (14128, 16, -1)
  10893.             RETURN (1)
  10894.         END
  10895.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  10896.         set @subscription_type_id = 0
  10897.     else 
  10898.         set @subscription_type_id = 1
  10899.  
  10900.  
  10901.     /*
  10902.     ** Parameter check: @offloadagent
  10903.     ** If @offloadagent = 1 then @subscription_type_id must be 0 
  10904.     */
  10905.     IF (@offloadagent = 1) AND (@subscription_type <> N'push') 
  10906.     BEGIN
  10907.         RAISERROR(21138, 16, -1)
  10908.         RETURN (1)
  10909.     END 
  10910.  
  10911.     /*
  10912.     ** Security Check.
  10913.     */
  10914.  
  10915.     IF @subscription_type_id = 0 
  10916.     BEGIN
  10917.         exec @retcode = dbo.sp_MSreplcheck_publish
  10918.         if @@ERROR <> 0 or @retcode <> 0
  10919.             return(1)
  10920.     END
  10921.     ELSE
  10922.     BEGIN
  10923.         exec @retcode = dbo.sp_MSreplcheck_pull @publication
  10924.         if @@ERROR <> 0 or @retcode <> 0
  10925.         begin
  10926.             return(1)
  10927.         end
  10928.     END
  10929.  
  10930.     /*
  10931.     ** Validate that the publisher is a valid server
  10932.     */
  10933.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  10934.     IF @publisher_srvid IS NULL
  10935.         BEGIN
  10936.             RAISERROR (14010, 16, -1)
  10937.             RETURN (1)
  10938.         END
  10939.  
  10940.     /*
  10941.     ** Parameter Check: @subscriber
  10942.     ** Check to make sure that the subscriber is defined
  10943.     */
  10944.     IF @subscriber IS NULL
  10945.         BEGIN
  10946.             RAISERROR (14043, 16, -1, '@subscriber')
  10947.             RETURN (1)
  10948.         END
  10949.  
  10950.      IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  10951.                      AND (srvstatus & @subscriber_bit) <> 0)
  10952.                BEGIN
  10953.                    RAISERROR (14010, 16, -1)
  10954.                    RETURN (1)
  10955.                END
  10956.  
  10957.     IF @subscriber = 'all'
  10958.         BEGIN
  10959.             RAISERROR (14136, 16, -1)
  10960.             RETURN (1)
  10961.         END
  10962.  
  10963.     /*
  10964.     ** Get distribution server information for remote RPC call.
  10965.     */
  10966.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  10967.          @distribdb   = @distribdb OUTPUT
  10968.     IF @@ERROR <> 0 or @retcode <> 0
  10969.         BEGIN
  10970.         GOTO FAILURE
  10971.         END
  10972.  
  10973.         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
  10974.             '.dbo.sp_MShelp_subscriber_info '
  10975.     exec @distproc @publisher, @subscriber, @found output
  10976.     if (@found <> 1) 
  10977.         BEGIN
  10978.             RAISERROR (14085, 16, -1)
  10979.             RETURN (1)
  10980.         END
  10981.  
  10982.     exec @retcode = dbo.sp_MSget_subtypedatasrc @subscriber, @distributor, @distribdb, @datasrctype OUTPUT, @datasrcpath OUTPUT
  10983.     if @retcode<>0
  10984.         return (1)
  10985.     if (@datasrctype = 2) or (@datasrctype = 4) or (@datasrctype = 5)
  10986.     BEGIN
  10987.         select @datasource_type = @datasrctype
  10988.         select @datasource_path = @datasrcpath
  10989.     END
  10990.     
  10991.     EXECUTE @retcode = dbo.sp_validname @subscriber
  10992.     IF @@ERROR <> 0 OR @retcode <> 0
  10993.        RETURN (1)
  10994.  
  10995.     /*
  10996.     ** Parameter Check: @subscriber_db
  10997.     */
  10998.     IF @subscriber_db IS NULL
  10999.     BEGIN
  11000.         RAISERROR (14043, 16, -1, '@subscriber_db')
  11001.         RETURN (1)
  11002.     END
  11003.  
  11004.     IF @subscriber_db = 'all'
  11005.     BEGIN
  11006.         RAISERROR (14136, 16, -1)
  11007.         RETURN (1)
  11008.     END
  11009.  
  11010.     /*
  11011.     **  Check to see if system tables exist. If not create them. Since under current
  11012.     **  design every database is qualified for subscribing.
  11013.     */
  11014.     
  11015.     IF not exists (select name from sysobjects where name='sysmergesubscriptions')
  11016.         BEGIN
  11017.             execute @retcode = dbo.sp_MScreate_mergesystables
  11018.                 if @@ERROR <> 0 or @retcode <> 0
  11019.                     begin
  11020.                         return (1)
  11021.                     end
  11022.         END 
  11023.         
  11024.     /*
  11025.     ** Parameter Check: @publication.
  11026.     ** Check to make sure that the publication exists and that it conforms
  11027.     ** to the rules for identifiers.
  11028.     */
  11029.     if NOT EXISTS (select * FROM sysmergepublications 
  11030.         WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
  11031.         BEGIN
  11032.             RAISERROR (20026, 16, -1, @publication)
  11033.             RETURN (1)
  11034.         END
  11035.  
  11036.     if @pubid IS NULL
  11037.         select @pubid = pubid FROM sysmergepublications 
  11038.             WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  11039.     if @partnerid IS NULL
  11040.         begin
  11041.             select @partnerid = subid FROM sysmergesubscriptions 
  11042.                 WHERE srvid = @publisher_srvid and db_name = @publisher_db and pubid = @pubid
  11043.         end                     
  11044.  
  11045.     /*
  11046.     ** Parameter Check: @subscriber_type.
  11047.     ** Set subscriber_typeid based on the @subscriber_type specified.
  11048.     **
  11049.     **   subscriber_type     subscriber_type
  11050.     **   =================    ===============
  11051.     **             1            global
  11052.     **             2            local
  11053.     **             3            anonymous
  11054.     **                          Type 'republisher' is taken out for B3. We may want to add this back later.
  11055.     */
  11056.     if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('local', 'global')
  11057.         BEGIN
  11058.             RAISERROR (20037, 16, -1)
  11059.             RETURN (1)
  11060.         END
  11061.  
  11062.     if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('global')
  11063.         set @subscriber_typeid = 1
  11064.     else if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('local')
  11065.         set @subscriber_typeid = 2
  11066.  
  11067.        /*
  11068.     ** Parameter Check: @use_interactive_resolver  
  11069.     */
  11070.     if LOWER(@use_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  11071.         BEGIN
  11072.             RAISERROR (14148, 16, -1, '@use_interactive_resolver')
  11073.             RETURN (1)
  11074.         END
  11075.     if LOWER(@use_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  11076.         set @use_interactive_bit = 1
  11077.     else 
  11078.         set @use_interactive_bit = 0
  11079.  
  11080.     
  11081.     /* 
  11082.     ** Assign priority appropriately - choose 0.99 times the minimum priority
  11083.     ** of the global replicas.
  11084.     */
  11085.     if (@subscription_priority >= 100.0 or @subscription_priority < 0.0)
  11086.         BEGIN
  11087.             RAISERROR (20088, 16, -1)
  11088.             RETURN (1)
  11089.         END
  11090.     if (@subscription_priority IS NULL)
  11091.         begin
  11092.             select @priority = 0.99 * min(priority) from sysmergesubscriptions where subscriber_type = 1
  11093.             if (@priority IS NOT NULL)
  11094.                 select @subscription_priority = @priority
  11095.             if (@subscription_priority IS NULL) 
  11096.                 select @subscription_priority = 0.0
  11097.         end
  11098.     /*
  11099.     ** For local and anonymous subscriptions the priority is 0.0
  11100.     */
  11101.     if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('local', 'anonymous')
  11102.         select @subscription_priority = 0.0
  11103.     
  11104.     /*
  11105.     ** Validate that the subscriber is a valid server
  11106.     */
  11107.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  11108.     IF @subscriber_srvid IS NULL
  11109.         BEGIN
  11110.             RAISERROR (14010, 16, -1)
  11111.             RETURN (1)
  11112.         END
  11113.  
  11114.     IF exists (select * from sysobjects where name= 'syssubscriptions')
  11115.     begin
  11116.         if exists (select name from sysmergeextendedarticlesview where pubid=@pubid and objid in
  11117.             (select objid from sysextendedarticlesview where artid in
  11118.                 (select artid from syssubscriptions where dest_db=@subscriber_db and srvid=@subscriber_srvid)))
  11119.         begin
  11120.             RAISERROR(21280, 16, -1, @publication, @subscriber_db)
  11121.             RETURN (1)
  11122.         end
  11123.     end
  11124.  
  11125.  
  11126.     /* 
  11127.     ** Make sure that @offloadserver doesn't contain invalid characters
  11128.     */
  11129.     exec @retcode = sp_MSreplcheckoffloadserver @offloadserver
  11130.     if @retcode<>0 or @@error<>0
  11131.         return (1)
  11132.  
  11133.     /*
  11134.     ** Making it possible for a deleted subscription to come back.
  11135.     ** UNDONE : This disallows second pull subscription from being added unless the previous 
  11136.     ** subscription was initial synced.
  11137.     */
  11138.     if EXISTS (select db_name, srvid
  11139.             FROM sysmergesubscriptions
  11140.             WHERE db_name = @subscriber_db
  11141.             AND srvid = @subscriber_srvid                          
  11142.             AND pubid = @pubid AND status <>2) --We can definitely add back subscriptions that were deleted.
  11143.         BEGIN
  11144.             RAISERROR (14058, 16, -1)
  11145.             RETURN (1)
  11146.         END
  11147.         
  11148.     IF EXISTS (select db_name, srvid FROM sysmergesubscriptions 
  11149.         WHERE db_name = @subscriber_db AND srvid = @subscriber_srvid AND pubid = @pubid AND status = 2) 
  11150.             BEGIN
  11151.                 select @subid = subid from sysmergesubscriptions 
  11152.                     WHERE db_name = @subscriber_db AND srvid = @subscriber_srvid AND pubid = @pubid
  11153.                 delete  from sysmergesubscriptions where subid = @subid
  11154.                 delete from MSmerge_replinfo where repid = @subid
  11155.             END
  11156.     select @subid = newid()    
  11157.     
  11158.    /*
  11159.    ** Parameter Check: @sync_type.
  11160.    ** Set sync_typeid based on the @sync_type specified.
  11161.    **
  11162.    **   sync_typeid     sync_type
  11163.    **   ===========     =========
  11164.    **             1     automatic
  11165.    **             2     none
  11166.    */
  11167.  
  11168.  
  11169.    IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('automatic', 'none')
  11170.        BEGIN
  11171.            RAISERROR (14052, 16, -1)
  11172.            RETURN (1)
  11173.        END
  11174.  
  11175.  
  11176.     /*
  11177.     ** If current publication contains an article without rowguidcol, do not allow no-sync subscription
  11178.     */
  11179.    IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) = 'automatic'
  11180.    BEGIN
  11181.         SET @sync_typeid = @automatic
  11182.    END
  11183.    ELSE
  11184.    BEGIN
  11185.         if exists (select * from sysmergearticles a where pubid=@pubid and 
  11186.             not exists (select * from syscolumns c where c.id = a.objid and ColumnProperty(c.id, c.name, 'IsRowGuidCol') = 1))
  11187.             
  11188.             BEGIN
  11189.                 Raiserror(20086, 16, -1, @publication)
  11190.                 RETURN (1)
  11191.             END
  11192.         else 
  11193.             SET @sync_typeid = @nosync
  11194.    END
  11195.  
  11196.  
  11197.     /*
  11198.     ** UNDONE: Validate that the publisher is of type "republisher"
  11199.     */
  11200.     begin tran
  11201.     save TRAN addmergesubscription
  11202.         /* Generate a guid for the Subscriber ID */
  11203.     
  11204.         /* Look for existing nickname from any other subscription */
  11205.         exec @retcode = dbo.sp_MSgetreplnick @subscriber, @subscriber_db , NULL,  @subnickname out
  11206.         if (@@error <> 0) or @retcode <> 0 
  11207.             GOTO FAILURE
  11208.             
  11209.         /* Generate a new replica nickname from the @subid */
  11210.         if (@subnickname is null)
  11211.         begin
  11212.             EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output
  11213.             if @@ERROR<>0 
  11214.                 GOTO FAILURE
  11215.         end
  11216.             
  11217.         /*
  11218.         ** The subscription doesn't exist, so let's add it to sysmergesubscriptions 
  11219.         */
  11220.         INSERT sysmergesubscriptions (subid, 
  11221.                                       partnerid,
  11222.                                       datasource_type, 
  11223.                                       datasource_path, 
  11224.                                       srvid, 
  11225.                                       db_name, 
  11226.                                       pubid,
  11227.                                       status, 
  11228.                                       subscriber_type,
  11229.                                       subscription_type,
  11230.                                       priority, 
  11231.                                       sync_type, 
  11232.                                       description,
  11233.                                       login_name,
  11234.                                       subscriber_server,
  11235.                                       use_interactive_resolver,
  11236.                                       publication,
  11237.                                       distributor)
  11238.                         VALUES (@subid,
  11239.                             @partnerid,
  11240.                             @datasource_type,
  11241.                             @datasource_path,
  11242.                             @subscriber_srvid,
  11243.                             @subscriber_db,
  11244.                             @pubid,
  11245.                             @inactive,
  11246.                             @subscriber_typeid,
  11247.                             @subscription_type_id,
  11248.                             @subscription_priority,
  11249.                             @sync_typeid,
  11250.                             @description,
  11251.                             suser_sname(suser_sid()),
  11252.                             @subscriber,
  11253.                             @use_interactive_bit,
  11254.                             @publication,
  11255.                             @distributor)          
  11256.         if @@ERROR <> 0
  11257.             BEGIN
  11258.                 GOTO FAILURE
  11259.             END
  11260.                 
  11261.         /*
  11262.         ** Get distribution server information for remote RPC call.
  11263.         */
  11264.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  11265.            @distribdb   = @distribdb OUTPUT
  11266.         IF @@ERROR <> 0 or @retcode <> 0
  11267.             BEGIN
  11268.                 GOTO FAILURE
  11269.             END
  11270.  
  11271.         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
  11272.             '.dbo.sp_MSadd_merge_subscription'
  11273.         EXEC @retcode = @distproc 
  11274.             @publisher = @@SERVERNAME, 
  11275.             @publisher_db = @publisher_db, 
  11276.             @publication = @publication,
  11277.             @subscriber = @subscriber, 
  11278.             @subscriber_db = @subscriber_db, 
  11279.             @subscription_type = @subscription_type_id,
  11280.             @sync_type = @sync_typeid, 
  11281.             @status = @inactive,
  11282.             @frequency_type = @frequency_type,
  11283.             @frequency_interval = @frequency_interval,
  11284.             @frequency_relative_interval = @frequency_relative_interval,
  11285.             @frequency_recurrence_factor = @frequency_recurrence_factor,
  11286.             @frequency_subday = @frequency_subday,
  11287.             @frequency_subday_interval = @frequency_subday_interval,
  11288.             @active_start_time_of_day = @active_start_time_of_day,
  11289.             @active_end_time_of_day = @active_end_time_of_day,
  11290.             @active_start_date = @active_start_date,
  11291.             @active_end_date = @active_end_date,
  11292.             @optional_command_line = @optional_command_line,
  11293.             @merge_jobid = @merge_jobid OUTPUT,
  11294.             @offloadagent = @offloadagent,
  11295.             @offloadserver = @offloadserver,
  11296.             @agent_name = @merge_job_name  
  11297.             
  11298.         IF @@ERROR <> 0 OR @retcode <> 0
  11299.             begin   
  11300.                 goto FAILURE
  11301.             end
  11302.             
  11303.         /*
  11304.         **  Add row for subscription in MSmerge_replinfo.
  11305.         */
  11306.         insert MSmerge_replinfo(repid, replnickname, merge_jobid)
  11307.                 values (@subid, @subnickname, @merge_jobid)
  11308.         if @@ERROR <> 0
  11309.             BEGIN
  11310.                 GOTO FAILURE
  11311.             END
  11312.  
  11313.         /* Conditional support for MobileSync */
  11314.         if LOWER(@enabled_for_syncmgr collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  11315.         BEGIN
  11316.  
  11317.             /* MobileSync Support */
  11318.             declare @distributor_server                 sysname
  11319.             declare @distributor_security_mode          int
  11320.             declare @distributor_login                  sysname
  11321.             declare @distributor_password               nvarchar(524)
  11322.  
  11323.             /* 
  11324.             ** The registry entry needs to be created only for push subscriptions -  
  11325.             ** i.e - need not be called when a pull subscription is created at the 
  11326.             ** subscriber and sp_addmergesubscription is being called then.
  11327.             */
  11328.             
  11329.             IF @subscription_type_id = 0 
  11330.             BEGIN
  11331.                 EXECUTE @retcode = dbo.sp_helpdistributor
  11332.                     @distributor = @distributor_server OUTPUT               /* Distributor RPC server name */
  11333.                 IF @@ERROR <> 0 or @retcode <> 0
  11334.                     BEGIN
  11335.                         GOTO FAILURE
  11336.                     END
  11337.  
  11338.                 -- Always use integrated security on winNT
  11339.                 if (@platform_nt = platform() & @platform_nt )
  11340.                     begin
  11341.                         set @distributor_security_mode = 1
  11342.                     end
  11343.                 -- For Win9x the dist publisher and distributor are the same machine                
  11344.                 else
  11345.                     begin
  11346.                         select  @distributor_security_mode = 0,
  11347.                             @distributor_login  = login,
  11348.                             @distributor_password = password
  11349.                         from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername) collate database_default
  11350.                     end
  11351.  
  11352.                 /* Call sp_MSregistersubscription so that the subscription can be synchronized via Onestop etc. */
  11353.                 exec @retcode = dbo.sp_MSregistersubscription @replication_type = 2,
  11354.                                     @publisher = @@SERVERNAME,
  11355.                                     @publisher_db = @publisher_db,
  11356.                                     @publication = @publication,
  11357.                                     @subscriber = @subscriber,
  11358.                                     @subscriber_db = @subscriber_db,
  11359.                                     @distributor = @distributor,
  11360.                                     @distributor_security_mode = @distributor_security_mode,
  11361.                                     @distributor_login = @distributor_login,
  11362.                                     @distributor_password = @distributor_password,
  11363.                                     @subscription_id = @subid,
  11364.                                     @subscription_type = @subscription_type_id,
  11365.                                     @use_interactive_resolver = @use_interactive_bit
  11366.                 IF @@error <> 0 OR @retcode <> 0
  11367.                     BEGIN
  11368.                         GOTO FAILURE
  11369.                     END
  11370.  
  11371.             END                                    
  11372.         END     
  11373.     COMMIT TRAN
  11374.     return (0)
  11375.  
  11376. FAILURE:
  11377.     RAISERROR (14057, 16, -1)
  11378.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  11379.     if @@TRANCOUNT > 0
  11380.     begin
  11381.         ROLLBACK TRANSACTION addmergesubscription
  11382.         COMMIT TRANSACTION
  11383.     end
  11384.     RETURN (1)
  11385.  
  11386. go
  11387. exec dbo.sp_MS_marksystemobject sp_addmergesubscription 
  11388. go
  11389.  
  11390. grant execute on dbo.sp_addmergesubscription to public
  11391. go
  11392.  
  11393. raiserror('Creating procedure sp_MSretrive_mergepublication', 0,1)
  11394. GO
  11395.  
  11396. CREATE PROCEDURE sp_MSretrieve_mergepublication 
  11397. @publication sysname
  11398. AS
  11399. declare @retcode int
  11400. /*
  11401. ** Security Check
  11402. */
  11403. exec @retcode = dbo.sp_MSreplcheck_publish
  11404. if @@ERROR <> 0 or @retcode <> 0
  11405.     return(1)
  11406.  
  11407. select    'name' = name, 
  11408.         'database ' = db_name(), 
  11409.         'publisher' = @@SERVERNAME, 
  11410.         'type' = 'Merge', 
  11411.         'description ' = description, 
  11412.         'status ' = status,  
  11413.         'allow known pull subscription' = allow_pull, 
  11414.         'allow immediate-updating subscription ' = 0,
  11415.         'allow anonymous ' = allow_anonymous,  
  11416.         'allow queued-updating subscription ' = 0, 
  11417.         'allow snapshot files FTP downloading' = enabled_for_internet, 
  11418.         'third party' = sync_mode 
  11419.     from sysmergepublications
  11420.     where name = @publication
  11421. go
  11422.  
  11423. EXEC dbo.sp_MS_marksystemobject sp_MSretrieve_mergepublication
  11424. GO
  11425.  
  11426. raiserror('Creating procedure sp_changemergesubscription', 0,1)
  11427. GO
  11428.  
  11429. CREATE PROCEDURE sp_changemergesubscription (
  11430.     @publication        sysname = NULL, /* Publication name */
  11431.     @subscriber         sysname = NULL,  /* Subscriber server */
  11432.     @subscriber_db      sysname = NULL,  /* Subscription database */
  11433.     @property           sysname = NULL, /* The property to change */
  11434.     @value              nvarchar(255) = NULL,    /* The new property value */
  11435.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  11436.     ) AS
  11437.  
  11438.     SET NOCOUNT ON
  11439.  
  11440.     /*
  11441.     ** Declarations.
  11442.     */
  11443.     declare @subscriber_bit         smallint
  11444.     declare @subscriber_srvid       int
  11445.     declare @publisher_srvid        int
  11446.     declare @retcode                int
  11447.     declare @pubid                  uniqueidentifier
  11448.     declare @subid                  uniqueidentifier
  11449.     declare @partnerid              uniqueidentifier
  11450.     declare @sync_typeid            tinyint
  11451.     declare @nosync                 tinyint
  11452.     declare @automatic              tinyint
  11453.      
  11454.     declare @artid                  uniqueidentifier
  11455.     declare @schematype             int
  11456.     declare @schemaversion          int
  11457.     declare @schemaguid             uniqueidentifier
  11458.     declare @db_name                sysname
  11459.     declare @subscriber_type        int
  11460.     declare @schematext             nvarchar(2000)
  11461.     declare @publisher              sysname
  11462.     declare @publisher_db           sysname
  11463.     declare @use_interactive_bit    bit 
  11464.     declare @enabled_for_syncmgr    int
  11465.     declare @regkey                    nvarchar(1000)
  11466.     declare @snapshot_ready            int
  11467.      
  11468.  
  11469.     /*
  11470.     ** Initializations.
  11471.     */
  11472.     SET @nosync         = 2     /* Const: synchronization type 'none' */
  11473.     SET @automatic      = 1     /* Const: synchronization type 'automatic' */
  11474.     set @publisher      = @@SERVERNAME
  11475.     set @publisher_db   = DB_NAME()
  11476.  
  11477.     /*
  11478.     ** Security Check.
  11479.     */
  11480.     BEGIN
  11481.         exec @retcode = dbo.sp_MSreplcheck_subscribe
  11482.         if @@ERROR <> 0 or @retcode <> 0
  11483.             return(1)
  11484.     END
  11485.  
  11486.  
  11487.     /*
  11488.     **  Check to see if current database is doing publishing/subscribing
  11489.     */
  11490.     IF not exists (select name from sysobjects where name='sysmergesubscriptions')
  11491.         BEGIN
  11492.             RAISERROR (14055, 16, -1)
  11493.             RETURN (1)
  11494.         END
  11495.  
  11496.     /*
  11497.     ** Parameter Check:  @property.
  11498.     ** If the @property parameter is NULL, print the options.
  11499.     */
  11500.  
  11501.     IF @property IS NULL
  11502.         BEGIN
  11503.             CREATE TABLE #tab1 (properties sysname collate database_default)
  11504.             INSERT INTO #tab1 VALUES ('sync_type')
  11505.             INSERT INTO #tab1 VALUES ('priority')
  11506.             INSERT INTO #tab1 VALUES ('description') 
  11507.             INSERT INTO #tab1 VALUES ('use_interactive_resolver') 
  11508.             select * FROM #tab1
  11509.             RETURN (0)
  11510.         END
  11511.  
  11512.     /*
  11513.     ** Parameter Check:  @publication.
  11514.     ** Make sure that the publication exists.
  11515.     */
  11516.  
  11517.     IF @publication IS NULL
  11518.         BEGIN
  11519.             RAISERROR (14043, 16, -1, '@publication')
  11520.             RETURN (1)
  11521.         END
  11522.  
  11523.     select @pubid = pubid, @snapshot_ready=snapshot_ready FROM sysmergepublications 
  11524.         WHERE name = @publication  and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  11525.     IF @pubid IS NULL
  11526.         BEGIN
  11527.             RAISERROR (20026, 11, -1, @publication)
  11528.             RETURN (1)
  11529.         END
  11530.  
  11531.     /*
  11532.     ** Validate that the publisher is a valid server
  11533.     */
  11534.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  11535.     IF @publisher_srvid IS NULL
  11536.         BEGIN
  11537.             RAISERROR (14010, 16, -1)
  11538.             RETURN (1)
  11539.         END
  11540.  
  11541.     /*
  11542.     ** Parameter Check:  @subscriber.
  11543.     ** Check to make sure we have a valid subscriber.
  11544.     */
  11545.     IF @subscriber IS NULL
  11546.         BEGIN
  11547.             RAISERROR (14043, 16, -1, '@subscriber')
  11548.             RETURN (1)
  11549.         END
  11550.     /*
  11551.     ** Validate that the subscriber is a valid server
  11552.     */
  11553.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  11554.     IF @subscriber_srvid IS NULL
  11555.         BEGIN
  11556.             RAISERROR (14010, 16, -1)
  11557.             RETURN (1)
  11558.         END
  11559.  
  11560.     /*
  11561.     ** Check to see if you have a local / global subscription on this publication
  11562.     */
  11563.     set @subid = NULL
  11564.     select @subid = subs1.subid, 
  11565.      
  11566.     @pubid = pubs.pubid, /* identified from publication name */
  11567.     @subscriber_type=subs1.subscriber_type,
  11568.      
  11569.         @partnerid = subs2.subid from
  11570.         sysmergesubscriptions   subs1,
  11571.         sysmergesubscriptions   subs2,
  11572.         sysmergepublications    pubs
  11573.         where subs1.srvid = @subscriber_srvid
  11574.             and subs1.db_name = @subscriber_db
  11575.             and subs2.srvid = @publisher_srvid
  11576.             and subs2.db_name = @publisher_db
  11577.             and subs1.pubid = subs2.subid
  11578.             and subs2.pubid = pubs.pubid
  11579.             and pubs.name = @publication 
  11580.             and UPPER(pubs.publisher)=UPPER(@@servername) 
  11581.             and pubs.publisher_db=db_name()
  11582.  
  11583.     if @subid IS NULL 
  11584.         begin
  11585.             RAISERROR (14050, 11, -1)
  11586.             RETURN(1)
  11587.         end                 
  11588.  
  11589.     /*
  11590.     ** Parameter Check:  @property.
  11591.     ** Check to make sure that @property is a valid property in
  11592.     ** sysarticles.
  11593.     */
  11594.  
  11595.     
  11596.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('sync_type', 'priority', 'description', 'use_interactive_resolver')
  11597.         BEGIN
  11598.             RAISERROR (20078, 16, -1)
  11599.             RETURN (1)
  11600.         END
  11601.  
  11602.  
  11603.     BEGIN TRANSACTION change_subscription
  11604.     save TRAN change_subscription
  11605.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'use_interactive_resolver'
  11606.         BEGIN
  11607.  
  11608.             /* Check to make sure that we have a true/false. */
  11609.  
  11610.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  11611.                 BEGIN
  11612.                     RAISERROR (14148, 16, -1, 'use_interactive_resolver')
  11613.                     goto UNDO    
  11614.                 END
  11615.  
  11616.             /* Determine the bit value. */
  11617.  
  11618.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  11619.                 SET @use_interactive_bit = 1
  11620.             ELSE
  11621.                 SET @use_interactive_bit = 0
  11622.     
  11623.             /* Update the subscription with the new 'use_interactive' value. */
  11624.  
  11625.             UPDATE sysmergesubscriptions
  11626.                    SET use_interactive_resolver = @use_interactive_bit
  11627.                  WHERE subid = @subid
  11628.             IF @@ERROR <> 0
  11629.                 BEGIN
  11630.                     RAISERROR (14053, 16, -1)
  11631.                     goto UNDO
  11632.                 END
  11633.  
  11634.             /* If the subscription is enable for Sync Manager, then update the reg value */
  11635.             exec sp_MSsubscription_enabled_for_syncmgr
  11636.                 @publisher, @publisher_db, @publication, @subscriber, @subscriber_db, 
  11637.                 @enabled_for_syncmgr OUT, @regkey OUT
  11638.             IF @@ERROR <> 0
  11639.                 BEGIN
  11640.                     RAISERROR (14053, 16, -1)
  11641.                     goto UNDO
  11642.                 END
  11643.             if @enabled_for_syncmgr = 1
  11644.                 begin
  11645.                     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  11646.                                            @regkey,
  11647.                                            'UseInteractiveResolver',
  11648.                                            'REG_DWORD',
  11649.                                             @use_interactive_bit
  11650.                     if @retcode <> 0 OR @@ERROR <> 0
  11651.                         BEGIN
  11652.                             RAISERROR (14053, 16, -1)
  11653.                             goto UNDO
  11654.                         END
  11655.                 end
  11656.         END
  11657.  
  11658.     /*
  11659.     ** Change the property.
  11660.     */
  11661.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_type'
  11662.         BEGIN 
  11663.             /*
  11664.             ** Check to make sure that we have a valid sync_type.
  11665.             */
  11666.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('automatic', 'none')
  11667.                 BEGIN
  11668.                     RAISERROR (14052, 16, -1)
  11669.                     goto UNDO
  11670.                 END
  11671.  
  11672.             /*
  11673.             ** Determine the integer value for the sync_type.
  11674.             */
  11675.  
  11676.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'automatic'
  11677.                 SET @sync_typeid = @automatic
  11678.             ELSE
  11679.             BEGIN
  11680.  
  11681.             /*
  11682.             **  If current publication contains an article without rowguidcol, do not allow no-sync subscription
  11683.             */    
  11684.             if exists (select * from sysmergearticles a where pubid = @pubid and 
  11685.                     not exists (select * from syscolumns c where c.id=a.objid and columnproperty (c.id, c.name, 'isrowguidcol')=1))
  11686.                 begin
  11687.                     Raiserror(20086, 16, -1, @publication)
  11688.                     goto UNDO
  11689.                 end
  11690.                 else 
  11691.                     SET @sync_typeid = @nosync
  11692.             END
  11693.  
  11694.             /*
  11695.             ** Update the subscription with the new sync_type.
  11696.             */
  11697.  
  11698.             UPDATE sysmergesubscriptions
  11699.                 SET sync_type = @sync_typeid
  11700.                 WHERE subid = @subid
  11701.             IF @@ERROR <> 0
  11702.                 BEGIN
  11703.                     RAISERROR (14053, 16, -1)
  11704.                     goto UNDO
  11705.                 END
  11706.  
  11707.             if @snapshot_ready>0
  11708.             begin
  11709.                 --if there is one article in this publication with pre_command of other than 'drop',
  11710.                 --do not allow changing subscription property.
  11711.                 if exists (select * from sysmergearticles where pubid=@pubid and pre_creation_command<>1)
  11712.                     begin
  11713.                         RAISERROR (21420, 16, -1, @property)
  11714.                         goto UNDO                
  11715.                     end
  11716.                 /*
  11717.                 ** make sure we know we really want to do this.
  11718.                 */
  11719.                 if @force_reinit_subscription = 0
  11720.                     begin
  11721.                         raiserror(20608, 16, -1)
  11722.                         goto UNDO
  11723.                     end
  11724.                 exec @retcode=sp_MSreinitmergepublication @publication
  11725.                 if @@ERROR<>0 or @retcode<>0
  11726.                     GOTO UNDO 
  11727.             end
  11728.         END
  11729.         
  11730.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'description'
  11731.         BEGIN
  11732.         UPDATE sysmergesubscriptions
  11733.                 SET description = @value
  11734.                 WHERE subid = @subid
  11735.             IF @@ERROR <> 0
  11736.                 BEGIN
  11737.                     RAISERROR (14053, 16, -1) 
  11738.               
  11739.                     goto UNDO
  11740.                 END
  11741.  
  11742.         END
  11743.         
  11744.      
  11745.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'priority'
  11746.     BEGIN
  11747.  
  11748.     select @db_name = db_name from sysmergesubscriptions
  11749.         where (pubid=@pubid) and (subid=@pubid)
  11750.         IF @db_name <> db_name()
  11751.         BEGIN
  11752.             RAISERROR (20047, 16, -1)
  11753.             goto UNDO
  11754.         END  
  11755.  
  11756.     /* Only the original publisher can change priority of a global subscriptions */
  11757.  
  11758.         IF @subscriber_type<>1  
  11759.             BEGIN
  11760.                 RAISERROR (20044, 16, -1)  /* Local subscriber does not have priority*/
  11761.                 goto UNDO
  11762.             END
  11763.  
  11764.         IF convert(real, @value)>100.0
  11765.             BEGIN
  11766.                 RAISERROR (20049, 16, -1)  /* Don't accept priority greater than 100 */
  11767.                 goto UNDO
  11768.             END
  11769.         
  11770.         exec dbo.sp_MSchange_priority @subid,  @value
  11771.         if @@ERROR<>0 goto UNDO
  11772.            /* Insert the sp_MSchange_priority schema change only if the publication's snapshot is ready */
  11773.         if (@snapshot_ready > 0)
  11774.             begin
  11775.                 select @schemaversion = schemaversion from sysmergeschemachange
  11776.                 if (@schemaversion is NULL)
  11777.                 set @schemaversion = 1
  11778.                 else
  11779.                     select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  11780.                     
  11781.                  
  11782.                 set @schemaguid = newid()
  11783.                 set @artid = newid()
  11784.                 set @schematype = 8 /* change priority */
  11785.                 select @schematext = 'exec dbo.sp_MSchange_priority '+ '''' + convert(nchar(36),@subid) + '''' + ',' + '''' + @value + '''' 
  11786.                 exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  11787.                 if @@ERROR<>0 or @retcode<>0 goto UNDO
  11788.             end                    
  11789.     END
  11790.  
  11791.     COMMIT TRANSACTION
  11792.  
  11793.     /*
  11794.     ** Return succeed. It is not an error message.
  11795.     */
  11796.  
  11797.     RAISERROR (14054, 10, -1)
  11798.     RETURN (0)
  11799. UNDO:
  11800.     if @@TRANCOUNT > 0
  11801.     begin
  11802.         ROLLBACK TRANSACTION change_subscription
  11803.         COMMIT TRANSACTION
  11804.     end
  11805.     return (1)
  11806. go
  11807.  
  11808. exec dbo.sp_MS_marksystemobject sp_changemergesubscription 
  11809. go
  11810.  
  11811. grant execute on dbo.sp_changemergesubscription to public
  11812. go
  11813.  
  11814. raiserror('Creating procedure sp_helpmergesubscription', 0,1)
  11815. GO
  11816.  
  11817. CREATE PROCEDURE sp_helpmergesubscription(
  11818.     @publication            sysname = '%',      /* Publication name */
  11819.     @subscriber             sysname = '%',      /* Subscriber server */
  11820.     @subscriber_db          sysname = '%',      /* Subscription database */
  11821.     @publisher              sysname = '%',      /* Publisher server */
  11822.     @publisher_db           sysname = '%',      /* Publisher database */
  11823.     @subscription_type      nvarchar(15) = 'both', /* Subscription type - push or pull */ 
  11824.     @found int = NULL OUTPUT
  11825.     )AS
  11826.  
  11827.     SET NOCOUNT ON
  11828.  
  11829.     /*
  11830.     ** Declarations.
  11831.     */
  11832.  
  11833.     declare @db                 sysname
  11834.     declare @retcode            int
  11835.     declare @subscriber_bit     smallint
  11836.     declare @srvid              int
  11837.     declare @pubid              uniqueidentifier
  11838.     declare @subid              uniqueidentifier
  11839.     declare @partnerid          uniqueidentifier
  11840.     declare @cursor_open        int
  11841.     declare @no_row             bit
  11842.     declare @subscription_type_id int
  11843.  
  11844.     declare @distributor    sysname
  11845.     declare @distributiondb sysname
  11846.     declare @distproc       nvarchar(300)
  11847.     declare @dbname         sysname
  11848.  
  11849.     select @distributor = null
  11850.     select @distributiondb = null
  11851.     select @distproc = null
  11852.     select @dbname = null    
  11853.  
  11854.     /*
  11855.     ** Initializations.
  11856.     */
  11857.     set @subscriber_bit     = 4
  11858.     set @cursor_open        = 0                 
  11859.  
  11860.     /*
  11861.     ** Initializations of @now_row.
  11862.     */
  11863.     IF @found is NULL
  11864.     BEGIN
  11865.         SELECT @no_row=0
  11866.     END
  11867.     ELSE
  11868.     BEGIN
  11869.         SELECT @no_row=1
  11870.     END
  11871.  
  11872.     select @db=db_name() -- so that it can appear in dynamic query
  11873.  
  11874.     /*
  11875.     **  Calling sp_help* is all right whether current database is enabled for pub/sub or not
  11876.     */
  11877.  
  11878.     IF not exists (select * from sysobjects where name='sysmergesubscriptions')
  11879.         RETURN (0)
  11880.     
  11881.     /* Security check */
  11882.     EXEC @retcode = dbo.sp_MSreplcheck_pull @publication = @publication, 
  11883.         @raise_fatal_error = 0
  11884.     if @@ERROR <> 0 or @retcode <> 0
  11885.         return(1)
  11886.  
  11887.     /*
  11888.     ** Parameter Check: @subscription_type.
  11889.     ** Set subscription_typeid based on the @subscription_type specified.
  11890.     **
  11891.     **   subscription_type    subscription_type
  11892.     **   =================    ===============
  11893.     **             0            push
  11894.     **             1            pull
  11895.     **            2         both
  11896.     */
  11897.     if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('push', 'pull', 'both')
  11898.         BEGIN
  11899.             RAISERROR (20079, 16, -1)
  11900.             RETURN (1)
  11901.         END
  11902.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'both'
  11903.         set @subscription_type_id = 2
  11904.     else IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  11905.         set @subscription_type_id = 0
  11906.     else 
  11907.         set @subscription_type_id = 1
  11908.  
  11909.     /*
  11910.     ** Parameter Check: @publisher
  11911.     ** Check to make sure that the publisher is defined
  11912.     */
  11913.     IF @publisher <> '%'
  11914.     BEGIN
  11915.         EXECUTE @retcode = dbo.sp_validname @publisher
  11916.         IF @@ERROR <> 0 OR @retcode <> 0
  11917.             RETURN (1)
  11918.     END
  11919.  
  11920.     /*
  11921.     ** Parameter Check:  @subscriber.
  11922.     ** If remote server, limit the view to the remote server's subscriptions.
  11923.     ** Make sure that the name isn't NULL.
  11924.     */
  11925.     if @subscriber IS NULL
  11926.         BEGIN
  11927.             RAISERROR (14043, 16, -1, '@subscriber')
  11928.             RETURN (1)
  11929.         END
  11930.  
  11931.     /*
  11932.     ** Parameter Check:  @subscriber.
  11933.     ** Check if remote server is defined as a subscription server, and
  11934.     ** that the name conforms to the rules for identifiers.
  11935.     */
  11936.  
  11937.     if @subscriber <> '%'
  11938.         BEGIN
  11939.             EXECUTE @retcode = dbo.sp_validname @subscriber
  11940.  
  11941.             if @retcode <> 0 OR @@ERROR <> 0
  11942.                 RETURN (1)
  11943.  
  11944.             if NOT EXISTS (select *
  11945.                             FROM master..sysservers
  11946.                             WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  11947.                             AND (srvstatus & @subscriber_bit) <> 0)
  11948.                 BEGIN
  11949.                     --RAISERROR (14010, 16, -1)
  11950.                     RETURN (1)
  11951.                 END
  11952.         END
  11953.  
  11954.     /*
  11955.     ** Parameter Check:  @publication.
  11956.     ** If the publication name is specified, check to make sure that it
  11957.     ** conforms to the rules for identifiers and that the publication
  11958.     ** actually exists.  Disallow NULL.
  11959.     */
  11960.     if @publication IS NULL
  11961.         BEGIN
  11962.             RAISERROR (14043, 16, -1, '@publication')
  11963.             RETURN (1)
  11964.         END
  11965.  
  11966.     /*
  11967.     ** Get subscriptions
  11968.     */
  11969.     if @publication <>'%'
  11970.     begin
  11971.         execute @retcode = dbo.sp_MSsubsetpublication @publication
  11972.         if @@ERROR <> 0 or @retcode<>0
  11973.                 Return (1)
  11974.     end
  11975.     
  11976.     create table #helpsubscription
  11977.                 (
  11978.                     publication             sysname     collate database_default not null,
  11979.                     publisher               sysname     collate database_default not null,
  11980.                     publisher_db            sysname     collate database_default not null,
  11981.                     subscriber              sysname     collate database_default not null,
  11982.                     subscriber_db           sysname     collate database_default not null,
  11983.                     status                  int         NOT NULL,
  11984.                     subscriber_type         int         NOT NULL,
  11985.                     subscription_type       int         NOT NULL,
  11986.                     priority                float(8)    NOT NULL,
  11987.                     sync_type               tinyint     NOT NULL,
  11988.                     description             nvarchar(255) collate database_default null,
  11989.                     merge_jobid             binary(16)  NULL,
  11990.                     full_publication        tinyint     NULL,
  11991.                     use_interactive_resolver     int        NULL
  11992.                 )
  11993.  
  11994.  
  11995.     /* 
  11996.     ** Performance Optimization: Eliminate the 'LIKE' clause for publication name.
  11997.     **                           Empirical evidence shows almost 50% speed improvement when
  11998.     **                           opening the cursor if publication name is provided.
  11999.     */
  12000.     IF (@publication <> '%')
  12001.         insert into #helpsubscription select distinct pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
  12002.                         subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
  12003.                         subs1.sync_type, subs1.description, replinfo.merge_jobid, pubs.publication_type,
  12004.                         subs1.use_interactive_resolver
  12005.  
  12006.                 FROM  sysmergesubscriptions     subs1,
  12007.                       sysmergesubscriptions     subs2,
  12008.                       MSmerge_replinfo      replinfo,
  12009.                       master..sysservers        servers1,
  12010.                       master..sysservers        servers2,
  12011.                       sysmergepublications  pubs
  12012.                     where subs1.subid <> subs2.subid 
  12013.                         and subs1.status <> 2 
  12014.                         and subs2.subid = subs1.partnerid
  12015.                         and pubs.pubid = subs1.pubid
  12016.                         and pubs.pubid = subs2.pubid
  12017.                         and servers1.srvid = subs1.srvid
  12018.                         and servers2.srvid = subs2.srvid
  12019.                         and pubs.name =  @publication 
  12020.                         and replinfo.repid = subs1.subid
  12021.                         and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)
  12022.                         and ((@subscriber_db = N'%') or (subs1.db_name = @subscriber_db collate database_default))
  12023.                         and ((@publisher_db = N'%') or (subs2.db_name = @publisher_db collate database_default))
  12024.                         and ((@subscriber = N'%') or (UPPER(servers1.srvname) = UPPER(@subscriber) collate database_default)) 
  12025.                         and ((@publisher = N'%') or (UPPER(servers2.srvname) = UPPER(@publisher) collate database_default))
  12026.                         and (subs1.subscription_type = @subscription_type_id or @subscription_type_id = 2)
  12027.     ELSE
  12028.         insert into #helpsubscription select distinct pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, 
  12029.                         subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, 
  12030.                         subs1.sync_type, subs1.description, replinfo.merge_jobid, pubs.publication_type,
  12031.                         subs1.use_interactive_resolver
  12032.  
  12033.                 FROM  sysmergesubscriptions     subs1,
  12034.                       sysmergesubscriptions     subs2,
  12035.                       MSmerge_replinfo      replinfo,
  12036.                       master..sysservers        servers1,
  12037.                       master..sysservers        servers2,
  12038.                       sysmergepublications  pubs
  12039.                     where subs1.subid <> subs2.subid 
  12040.                         and subs1.status <> 2 
  12041.                         and subs2.subid = subs1.partnerid
  12042.                         and pubs.pubid = subs1.pubid
  12043.                         and pubs.pubid = subs2.pubid
  12044.                         and servers1.srvid = subs1.srvid
  12045.                         and servers2.srvid = subs2.srvid
  12046.                         and replinfo.repid = subs1.subid
  12047.                         and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)
  12048.                         and ((@subscriber_db = N'%') or (subs1.db_name = @subscriber_db collate database_default))
  12049.                         and ((@publisher_db = N'%') or (subs2.db_name = @publisher_db collate database_default)) 
  12050.                         and ((@subscriber = N'%') or (UPPER(servers1.srvname) = UPPER(@subscriber) collate database_default)) 
  12051.                         and ((@publisher = N'%') or (UPPER(servers2.srvname) = UPPER(@publisher) collate database_default))
  12052.                         and (subs1.subscription_type = @subscription_type_id or @subscription_type_id = 2)
  12053.         
  12054.  
  12055.     if exists (select * from #helpsubscription)
  12056.         select @found = 1
  12057.     else
  12058.         select @found = 0 
  12059.         
  12060.     if @no_row = 1
  12061.         goto DONE
  12062.  
  12063.     CREATE TABLE #merge_agent_properties
  12064.     (
  12065.         job_id                VARBINARY(16) NOT NULL,
  12066.         offload_enabled       bit NULL,
  12067.         offload_server        sysname collate database_default null
  12068.     )
  12069.  
  12070.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  12071.                                            @distribdb = @distributiondb OUTPUT
  12072.     IF @retcode <> 0
  12073.         GOTO DONE
  12074.  
  12075.     SELECT @distributor = RTRIM(@distributor)
  12076.  
  12077.     -- Get distribution agent properties 
  12078.     IF LOWER(@@SERVERNAME) <> LOWER(@distributor)
  12079.     BEGIN
  12080.         SELECT @distproc = @distributor + '.' + @distributiondb + 
  12081.                            '.dbo.sp_MSenum_merge_agent_properties'
  12082.     END    
  12083.     ELSE
  12084.     BEGIN
  12085.         SELECT @distproc = @distributiondb + 
  12086.                            '.dbo.sp_MSenum_merge_agent_properties'
  12087.     END
  12088.  
  12089.     SELECT @dbname = db_name()
  12090.  
  12091.     INSERT INTO #merge_agent_properties
  12092.       EXEC @retcode = @distproc @publisher = @@SERVERNAME, 
  12093.                                 @publisher_db = @dbname, 
  12094.                                 @publication = @publication            
  12095.  
  12096.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push' or LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'both'
  12097.         begin
  12098.             select 'subscription_name'  = subscriber + ':' + subscriber_db,
  12099.                 hs.publication, hs.publisher, hs.publisher_db, 
  12100.                 hs.subscriber, hs.subscriber_db, hs.status, hs.subscriber_type,
  12101.                 hs.subscription_type, hs.priority, hs.sync_type, hs.description,
  12102.                 hs.merge_jobid, hs.full_publication,
  12103.                 ap.offload_enabled, ap.offload_server,
  12104.                 hs.use_interactive_resolver
  12105.                 from #helpsubscription hs
  12106.                 left outer join #merge_agent_properties ap
  12107.                 on hs.merge_jobid = ap.job_id
  12108.                 order by hs.publisher, hs.publisher_db, hs.publication, hs.subscriber, hs.subscriber_db
  12109.         end
  12110.     else 
  12111.         begin
  12112.             select 'subscription_name' = hs.publisher + ':' + hs.publisher_db + ':' + hs.publication, 
  12113.                 hs.publication, hs.publisher, hs.publisher_db, 
  12114.                 hs.subscriber, hs.subscriber_db, hs.status, hs.subscriber_type,
  12115.                 hs.subscription_type, hs.priority, hs.sync_type, hs.description,
  12116.                 hs.merge_jobid, hs.full_publication,
  12117.                 ap.offload_enabled, ap.offload_server,                 
  12118.                 hs.use_interactive_resolver
  12119.                 from #helpsubscription hs
  12120.                 left outer join #merge_agent_properties ap
  12121.                 on hs.merge_jobid = ap.job_id
  12122.                 order by hs.publisher, hs.publisher_db, hs.publication, hs.subscriber, hs.subscriber_db
  12123.         end
  12124.  
  12125.     drop table #merge_agent_properties
  12126.     select @retcode = 0
  12127. DONE:
  12128.     if (@cursor_open = 1)
  12129.         begin
  12130.             close #cursor
  12131.             deallocate #cursor
  12132.         end         
  12133.     drop table #helpsubscription
  12134.     return @retcode 
  12135. go
  12136. exec dbo.sp_MS_marksystemobject sp_helpmergesubscription
  12137. go
  12138.  
  12139. grant execute on dbo.sp_helpmergesubscription to public
  12140. go
  12141.  
  12142. raiserror('Creating procedure sp_dropmergesubscription', 0,1)
  12143. GO
  12144. CREATE PROCEDURE sp_dropmergesubscription(
  12145.     @publication        sysname = NULL,             /* Publication name */
  12146.     @subscriber         sysname = NULL,             /* Subscriber server */
  12147.     @subscriber_db      sysname = NULL,             /* Subscription database */
  12148.     @subscription_type  nvarchar(15) = 'both',          /* Subscription type - push, pull, both */ 
  12149.     @ignore_distributor bit = 0,
  12150.     @reserved             bit = 0
  12151.     )AS
  12152.  
  12153.     SET NOCOUNT ON
  12154.  
  12155.     /*
  12156.     ** Declarations.
  12157.     */
  12158.     declare @retcode                int
  12159.     declare @subscriber_bit         smallint
  12160.     declare @subscriber_type        smallint
  12161.     declare @subscriber_srvid       int
  12162.     declare @publisher_srvid        int
  12163.     declare @pubid                  uniqueidentifier
  12164.     declare @subid                  uniqueidentifier
  12165.     declare @partnerid              uniqueidentifier
  12166.     declare @subscription_type_id   int   
  12167.     declare @found_subscription     int   
  12168.     declare @local_server           sysname
  12169.     declare @local_db               sysname
  12170.     declare @cmd                    nvarchar(290)
  12171.     declare @distributor            sysname
  12172.     declare @distribdb              sysname
  12173.     declare @distproc               nvarchar(300)
  12174.     declare @pubidstr               nvarchar(38)
  12175.     declare @publisher              sysname
  12176.     declare @publisher_db           sysname
  12177.  
  12178.     declare @implicit_transaction    int
  12179.     declare @close_cursor_at_commit int
  12180.  
  12181.     select @close_cursor_at_commit = 0
  12182.     select @implicit_transaction = 0
  12183.  
  12184.     /*
  12185.     ** Save setting values first before changing them
  12186.     */
  12187.     IF (@reserved = 0)
  12188.     BEGIN
  12189.         SELECT @implicit_transaction = @@options & 2
  12190.         SELECT @close_cursor_at_commit = @@options & 4
  12191.         SET IMPLICIT_TRANSACTIONS OFF
  12192.         SET CURSOR_CLOSE_ON_COMMIT OFF
  12193.     END
  12194.  
  12195.      /*
  12196.     ** Initializations.
  12197.     */
  12198.     set @subscriber_bit     = 4
  12199.     set @subscription_type_id = -1
  12200.     set @found_subscription = 0                     
  12201.     set @local_db           = DB_NAME()
  12202.     set @local_server       = @@SERVERNAME
  12203.     set @publisher          = @@SERVERNAME
  12204.     set @publisher_db       = DB_NAME()
  12205.  
  12206.     /*
  12207.     **  Check to see if current database is enabled for publishing/subscribing
  12208.     */
  12209.     IF not exists (select name from sysobjects where name='sysmergesubscriptions')
  12210.         BEGIN
  12211.             RAISERROR (14055, 16, -1)
  12212.             RETURN (1)
  12213.         END
  12214.  
  12215.     /*
  12216.     ** Parameter Check: @subscription_type.
  12217.     ** Set subscription_typeid based on the @subscription_type specified.
  12218.     **
  12219.     **   subscription_type    subscription_type
  12220.     **   =================    ===============
  12221.     **             0            push
  12222.     **             1            pull
  12223.     */
  12224.     if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('both', 'push', 'pull')
  12225.         BEGIN
  12226.             RAISERROR (14128, 16, -1)
  12227.             RETURN (1)
  12228.         END
  12229.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'both'
  12230.         begin
  12231.             EXECUTE @retcode = dbo.sp_dropmergesubscription @publication = @publication,
  12232.                             @subscriber = @subscriber,
  12233.                             @subscriber_db = @subscriber_db,
  12234.                             @subscription_type = 'push',
  12235.                             @ignore_distributor = @ignore_distributor,
  12236.                             @reserved = 1
  12237.             if @retcode<>0 or @@ERROR<>0
  12238.                 return (1)
  12239.             EXECUTE @retcode = dbo.sp_dropmergesubscription @publication = @publication,
  12240.                             @subscriber = @subscriber,
  12241.                             @subscriber_db = @subscriber_db,
  12242.                             @subscription_type = 'pull',
  12243.                             @ignore_distributor = @ignore_distributor,
  12244.                             @reserved = 1
  12245.             if @retcode<>0 or @@ERROR<>0
  12246.                 return (1)
  12247.             return (0)
  12248.         end 
  12249.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  12250.         set @subscription_type_id = 0
  12251.     else 
  12252.         set @subscription_type_id = 1
  12253.  
  12254.     /*
  12255.     ** Parameter validation (different for push and pull modes)
  12256.     */
  12257.  
  12258.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  12259.         begin
  12260.             /*
  12261.             ** Assign parameter values appropriately
  12262.             */
  12263.             if @publisher IS NULL
  12264.                 set @publisher = @@SERVERNAME
  12265.             if (@publisher_db IS NULL)
  12266.                 set @publisher_db = DB_NAME()
  12267.  
  12268.             /*
  12269.             ** Parameter Check: @subscriber
  12270.             ** Check to make sure that the subscriber is defined
  12271.             */
  12272.             IF @subscriber IS NULL
  12273.             BEGIN
  12274.                 RAISERROR (14043, 16, -1, '@subscriber')
  12275.                 RETURN (1)
  12276.             END
  12277.  
  12278.             /*
  12279.             ** Parameter Check: @subscriber_db
  12280.             */
  12281.             IF @subscriber_db IS NULL
  12282.             BEGIN
  12283.                 select @subscriber_db = 'all'
  12284.             END
  12285.                 
  12286.         end
  12287.     else
  12288.         begin
  12289.             /*
  12290.             ** Assign parameter values appropriately
  12291.             */
  12292.             if @subscriber IS NULL
  12293.                 set @subscriber = @@SERVERNAME
  12294.             if @subscriber_db IS NULL
  12295.                 set @subscriber_db = DB_NAME()
  12296.  
  12297.             /*
  12298.             ** Parameter Check: @publisher
  12299.             ** Check to make sure that the publisher is defined
  12300.             */
  12301.             IF @publisher IS NULL
  12302.             BEGIN
  12303.                 RAISERROR (14043, 16, -1, '@publisher')
  12304.                 RETURN (1)
  12305.             END
  12306.  
  12307.             EXECUTE @retcode = dbo.sp_validname @publisher
  12308.             IF @@ERROR <> 0 OR @retcode <> 0
  12309.                RETURN (1)
  12310.  
  12311.             /*
  12312.             ** Parameter Check: @publisher_db
  12313.             */
  12314.             IF @publisher_db IS NULL
  12315.             BEGIN
  12316.                 RAISERROR (14043, 16, -1, '@publisher_db')
  12317.                 RETURN (1)
  12318.             END
  12319.  
  12320.         end     
  12321.  
  12322.     /*
  12323.     ** Parameter Check:  @publication.
  12324.     ** If the publication name is specified, check to make sure that it
  12325.     ** conforms to the rules for identifiers and that the publication
  12326.     ** actually exists.  Disallow NULL.
  12327.     */
  12328.     if @publication IS NULL
  12329.         BEGIN
  12330.             RAISERROR (14043, 16, -1, '@publication')
  12331.             RETURN (1)
  12332.         END
  12333.  
  12334.     IF LOWER(@publication) = 'all'
  12335.         BEGIN
  12336.             declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergepublications 
  12337.                 where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() 
  12338.                 FOR READ ONLY
  12339.             
  12340.             OPEN hC1
  12341.             FETCH hC1 INTO @publication
  12342.             WHILE (@@fetch_status <> -1)
  12343.                 BEGIN
  12344.                     EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
  12345.                                                 @subscriber = @subscriber,
  12346.                                                 @subscriber_db = @subscriber_db,
  12347.                                                 @subscription_type = @subscription_type,
  12348.                                                 @ignore_distributor = @ignore_distributor,
  12349.                                                 @reserved = 1
  12350.                     FETCH hC1 INTO @publication
  12351.                 END
  12352.             CLOSE hC1
  12353.             DEALLOCATE hC1
  12354.             RETURN (0)
  12355.         END
  12356.         
  12357.     if NOT EXISTS (select * FROM sysmergepublications 
  12358.         WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name())
  12359.         BEGIN
  12360.             RAISERROR (20026, 16, -1, @publication)
  12361.             RETURN (1)
  12362.         END
  12363.     select @pubid = pubid from sysmergepublications 
  12364.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  12365.     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  12366.     if @pubid is null
  12367.         BEGIN
  12368.             RAISERROR (20026, 16, -1, @publication)
  12369.             RETURN (1)
  12370.         END
  12371.  
  12372.        
  12373.     IF LOWER(@subscriber) = 'all'
  12374.         BEGIN
  12375.             declare hC2 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname 
  12376.             FROM master..sysservers 
  12377.             WHERE (srvstatus & 4 <> 0) FOR READ ONLY
  12378.     
  12379.             OPEN hC2
  12380.             FETCH hC2 INTO @subscriber
  12381.             WHILE (@@fetch_status <> -1)
  12382.                 BEGIN
  12383.                     EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
  12384.                                                 @subscriber = @subscriber,
  12385.                                                 @subscriber_db = @subscriber_db,
  12386.                                                 @subscription_type = @subscription_type,
  12387.                                                 @ignore_distributor = @ignore_distributor,
  12388.                                                 @reserved = 1
  12389.                     FETCH hC2 INTO @subscriber
  12390.                 END
  12391.             CLOSE hC2
  12392.             DEALLOCATE hC2
  12393.             RETURN (0)
  12394.         END
  12395.  
  12396.     /*
  12397.     ** Validate that the subscriber is a valid server
  12398.     */
  12399.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  12400.     IF @subscriber_srvid IS NULL
  12401.         BEGIN
  12402.             --RAISERROR (14010, 16, -1)
  12403.             RETURN (1)
  12404.         END
  12405.  
  12406.     /*
  12407.     ** NOTE: remove this batch
  12408.     */
  12409.     IF LOWER(@subscriber_db) = 'all'
  12410.         BEGIN
  12411.                 declare hC3 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions
  12412.                 WHERE srvid =  @subscriber_srvid 
  12413.                     AND subid <> pubid 
  12414.                     AND sysmergesubscriptions.pubid = @pubid
  12415.                     AND sysmergesubscriptions.subscription_type = @subscription_type_id
  12416.                 FOR READ ONLY       
  12417.  
  12418.             OPEN hC3
  12419.             FETCH hC3 INTO @subscriber_db
  12420.             WHILE (@@fetch_status <> -1)
  12421.                 BEGIN
  12422.                     EXECUTE dbo.sp_dropmergesubscription @publication = @publication,
  12423.                                                 @subscriber = @subscriber,
  12424.                                                 @subscriber_db = @subscriber_db,
  12425.                                                 @subscription_type = @subscription_type,
  12426.                                                 @ignore_distributor = @ignore_distributor,
  12427.                                                 @reserved = 1
  12428.  
  12429.                     FETCH hC3 INTO @subscriber_db
  12430.                 END
  12431.             CLOSE hC3
  12432.             DEALLOCATE hC3
  12433.             RETURN (0)
  12434.         END
  12435.  
  12436.     /*
  12437.     ** Validate that the publisher is a valid server
  12438.     */
  12439.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  12440.     IF @publisher_srvid IS NULL
  12441.         BEGIN
  12442.             --RAISERROR (14010, 16, -1)
  12443.             RETURN (1)
  12444.         END
  12445.  
  12446.     select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  12447.     if @pubid is NULL return (0)
  12448.     
  12449.     if exists (select * from sysmergesubscriptions where subid=@pubid 
  12450.         and pubid=@pubid and db_name<>db_name())
  12451.     RETURN (0)
  12452.     
  12453.     /*
  12454.     ** Get subscriptions from either local replicas or global replicas
  12455.     */
  12456.     select @subid = subs1.subid, @partnerid = subs2.subid, @subscriber_type = subs1.subscriber_type from
  12457.         sysmergesubscriptions   subs1,
  12458.         sysmergesubscriptions   subs2,
  12459.         sysmergepublications        pubs
  12460.         where subs1.srvid = @subscriber_srvid
  12461.             and subs1.db_name = @subscriber_db
  12462.             and subs2.srvid = @publisher_srvid
  12463.             and subs2.db_name = @publisher_db
  12464.             and subs1.pubid = subs2.subid
  12465.             and subs2.pubid = pubs.pubid
  12466.             and pubs.name = @publication
  12467.             and UPPER(pubs.publisher)=UPPER(@@servername)
  12468.             and pubs.publisher_db=db_name()
  12469.             and subs1.subscription_type = @subscription_type_id
  12470.             and (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1)
  12471.  
  12472.     if @subid IS NULL
  12473.         begin
  12474.             -- raiserror (14050, 16, -1) 
  12475.             RETURN (0)
  12476.         end                 
  12477.  
  12478.     begin tran
  12479.     save TRAN dropmergesubscription
  12480.  
  12481.         /*
  12482.         ** Do not drop the subscription corresponding to the loopback subscription 
  12483.         */
  12484.         if (@subid <> @partnerid) 
  12485.             begin
  12486.                 /*
  12487.                 ** global/republisher subscriptions have to stay for a while even after being
  12488.                 ** dropped so that they won't regain lives for themselves. They would be cleanup eventually.
  12489.                 */
  12490.                 
  12491.                 if (@subscriber_type<>1) 
  12492.                     begin
  12493.                         delete from sysmergesubscriptions where subid = @subid
  12494.                         IF @@ERROR <> 0
  12495.                             GOTO FAILURE        
  12496.                         delete MSmerge_replinfo WHERE repid = @subid 
  12497.                         IF @@ERROR <> 0
  12498.                             GOTO FAILURE
  12499.                     end
  12500.                 else
  12501.                     begin
  12502.                         update sysmergesubscriptions set status=2 where subid=@subid
  12503.                         IF @@ERROR<>0
  12504.                             GOTO FAILURE
  12505.                     end 
  12506.  
  12507.                 /* 
  12508.                 ** The MobileSync registry entry needs to be dropped only for push subscriptions -  
  12509.                 ** i.e - need not be called when a pull subscription is created at the 
  12510.                 ** subscriber and sp_addmergesubscription is being called then.
  12511.                 */
  12512.                 IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  12513.                 begin
  12514.                     /* Call sp_MSunregistersubscription so that the reg entries get deleted */
  12515.                     exec @retcode = dbo.sp_MSunregistersubscription @publisher = @@SERVERNAME,
  12516.                                     @publisher_db = @publisher_db,
  12517.                                     @publication = @publication,
  12518.                                     @subscriber = @subscriber,
  12519.                                     @subscriber_db = @subscriber_db
  12520.                     IF @retcode<>0 or @@ERROR<>0
  12521.                         GOTO FAILURE
  12522.  
  12523.                 END             
  12524.             end     
  12525.  
  12526.         /*
  12527.         ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  12528.         */
  12529.         if @ignore_distributor = 0
  12530.         begin
  12531.             /*
  12532.             ** Get distribution server information for remote RPC call.
  12533.             */
  12534.             EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  12535.                @distribdb   = @distribdb OUTPUT
  12536.             IF @@ERROR <> 0 or @retcode <> 0
  12537.                 BEGIN
  12538.                     GOTO FAILURE
  12539.                 END
  12540.  
  12541.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + 
  12542.                 '.dbo.sp_MSdrop_merge_subscription'
  12543.  
  12544.             EXEC @retcode = @distproc 
  12545.                 @@SERVERNAME, 
  12546.                 @publisher_db, 
  12547.                 @publication,
  12548.                 @subscriber, 
  12549.                 @subscriber_db,
  12550.                 @subscription_type
  12551.             IF @@ERROR <> 0 OR @retcode <> 0
  12552.                 begin   
  12553.                     goto FAILURE
  12554.                 end 
  12555.         end 
  12556.  
  12557.         /* 
  12558.         ** If last subscription is dropped and the DB is not enabled for publishing,
  12559.         ** then remove the merge system tables
  12560.         */
  12561.  
  12562.         IF (not exists (select * from sysmergesubscriptions )) 
  12563.             AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME() collate database_default)=0
  12564.             BEGIN
  12565.                 execute @retcode = dbo.sp_MSdrop_mergesystables
  12566.                 if @@ERROR <> 0 or @retcode <> 0
  12567.                     begin
  12568.                         return (1)
  12569.                     end
  12570.             END         
  12571.  
  12572.     COMMIT TRAN
  12573.     /*
  12574.     ** Set back original settings
  12575.     */    
  12576.     IF @reserved = 0
  12577.     BEGIN
  12578.         IF @implicit_transaction <>0 
  12579.             SET IMPLICIT_TRANSACTIONS ON
  12580.         IF @close_cursor_at_commit <>0 
  12581.             SET CURSOR_CLOSE_ON_COMMIT ON
  12582.     END
  12583.     RETURN(0)       
  12584.  
  12585. FAILURE:
  12586.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  12587.     RAISERROR (14056, 16, -1)
  12588.     if @@TRANCOUNT > 0
  12589.     begin
  12590.         ROLLBACK TRANSACTION dropmergesubscription
  12591.         COMMIT TRANSACTION
  12592.     end
  12593.     /*
  12594.     ** Set back original settings
  12595.     */    
  12596.     IF @reserved = 0
  12597.     BEGIN
  12598.         IF @implicit_transaction <>0 
  12599.             SET IMPLICIT_TRANSACTIONS ON
  12600.         IF @close_cursor_at_commit <>0 
  12601.             SET CURSOR_CLOSE_ON_COMMIT ON
  12602.     END
  12603.     return (1)
  12604. go
  12605. exec dbo.sp_MS_marksystemobject sp_dropmergesubscription
  12606. go
  12607.  
  12608. grant execute on dbo.sp_dropmergesubscription to public
  12609. go
  12610.  
  12611. raiserror('Creating procedure sp_MShelpvalidationdate', 0,1)
  12612. GO
  12613.  
  12614. CREATE PROCEDURE sp_MShelpvalidationdate(
  12615. @publication        sysname,
  12616. @subscriber            sysname,
  12617. @subscriber_db        sysname
  12618. )AS
  12619. declare @pubid                    uniqueidentifier
  12620. declare @subscriber_srvid        int
  12621.  
  12622. select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  12623. if @pubid is NULL return (0)
  12624. select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  12625. select last_validated, attempted_validate from sysmergesubscriptions where pubid=@pubid and db_name=@subscriber_db and srvid=@subscriber_srvid
  12626.  
  12627. return (0)
  12628. GO
  12629. exec dbo.sp_MS_marksystemobject sp_MShelpvalidationdate
  12630. go
  12631.  
  12632.  
  12633. raiserror('Creating procedure sp_MSmergepublishdb', 0,1)
  12634. GO
  12635.  
  12636. CREATE PROCEDURE sp_MSmergepublishdb(
  12637.       @value     sysname,
  12638.       @ignore_distributor bit = 0
  12639.     ) AS
  12640.  
  12641.     SET NOCOUNT ON
  12642.  
  12643.     /*
  12644.     ** Declarations.
  12645.     */
  12646.     declare @command        nvarchar(255)
  12647.     declare @description    nvarchar(500)
  12648.     declare @cmptlevel      tinyint
  12649.     declare @db_name        sysname 
  12650.     declare @retcode        int
  12651.     declare @distributor    sysname
  12652.     declare @distribdb      sysname
  12653.     declare @category_name  sysname
  12654.     declare @agentname      sysname
  12655.     declare @working_directory nvarchar(255)
  12656.     /*
  12657.     ** Initialization
  12658.     */
  12659.  
  12660.     select @db_name = DB_NAME()
  12661.  
  12662.  
  12663.     /*
  12664.     ** Parameter check
  12665.     ** @value
  12666.     */
  12667.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false')
  12668.     BEGIN
  12669.       RAISERROR(14137,16,-1)
  12670.       RETURN(1)
  12671.     END
  12672.  
  12673.     /*
  12674.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  12675.     */
  12676.     if @ignore_distributor = 0
  12677.     begin
  12678.         /*
  12679.         ** Test to see if the distributor is installed and online.
  12680.         */
  12681.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @directory=@working_directory OUTPUT,
  12682.            @distribdb   = @distribdb OUTPUT
  12683.  
  12684.         IF @@ERROR <> 0 or @retcode <> 0 or @distributor IS NULL or @distribdb IS NULL
  12685.         BEGIN
  12686.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  12687.                 RAISERROR (20028, 16, -1)
  12688.             ELSE
  12689.                 RAISERROR (20029, 16, -1)
  12690.             RETURN (1)
  12691.         END
  12692.     end
  12693.  
  12694.     /*
  12695.     ** Enable the database for publishing.
  12696.     */
  12697.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  12698.         BEGIN
  12699.             select @cmptlevel = cmptlevel from master..sysdatabases where name=db_name() collate database_default
  12700.             if @cmptlevel<70 OR @cmptlevel is NULL 
  12701.                 begin
  12702.                     RAISERROR(20061, 16, -1)
  12703.                     goto FAILURE
  12704.                 end
  12705.             execute @retcode = dbo.sp_MScreate_mergesystables
  12706.             if @@ERROR <> 0 or @retcode <> 0
  12707.                 begin
  12708.                     goto FAILURE
  12709.                 end
  12710.  
  12711.             END
  12712.  
  12713.     ELSE    /* Disable the database for publishing. */
  12714.         BEGIN 
  12715.            
  12716.           /*
  12717.           ** Remove all the registration entries for subscriptions
  12718.           */
  12719.             if not exists(select * from sysobjects where name = 'sysmergesubscriptions')
  12720.                 goto FAILURE
  12721.             exec @retcode = dbo.sp_dropmergesubscription @publication = 'all', 
  12722.                                             @subscriber = 'all', 
  12723.                                             @subscriber_db = 'all', 
  12724.                                             @subscription_type = 'both',
  12725.                                             @ignore_distributor = @ignore_distributor
  12726.             IF @@ERROR <> 0 or @retcode <> 0 
  12727.                 begin
  12728.                     goto FAILURE
  12729.                 end
  12730.             /*
  12731.             ** Remove all publications and articles in the database.
  12732.             */
  12733.             EXEC @retcode = dbo.sp_dropmergepublication @publication = 'all',
  12734.                 @ignore_distributor = @ignore_distributor
  12735.             IF @@ERROR <> 0 or @retcode <> 0 
  12736.                 begin
  12737.                     -- sp_dropmergepublication will raiserror 
  12738.                     goto FAILURE
  12739.                 end
  12740.                 
  12741.             If NOT EXISTS (select * from sysmergepublications)
  12742.                 BEGIN
  12743.                     execute @retcode = dbo.sp_MSdrop_mergesystables
  12744.                     if @@ERROR <> 0 or @retcode <> 0
  12745.                         begin
  12746.                             goto FAILURE
  12747.                         end
  12748.                 END
  12749.     
  12750.     END
  12751.         
  12752.         
  12753.         return 0
  12754. FAILURE:
  12755.     
  12756.     return (1)  
  12757.  
  12758. GO
  12759. exec dbo.sp_MS_marksystemobject sp_MSmergepublishdb
  12760. go
  12761.  
  12762. raiserror('Creating procedure sp_enumcustomresolvers', 0,1)
  12763. GO
  12764.  
  12765. CREATE PROCEDURE sp_enumcustomresolvers
  12766. --    @distributor parameter will be removed in the next version.   
  12767.     @distributor     sysname = NULL
  12768.     AS
  12769.     SET NOCOUNT ON
  12770.  
  12771.     declare @distributor_rpc sysname
  12772.     declare @return_status int
  12773.     declare @distproc nvarchar(150)
  12774.     declare @retcode int
  12775.  
  12776.     select @return_status = 0
  12777.  
  12778.    
  12779.     /*
  12780.     ** Get the distributor 
  12781.     ** Use local RPC if @distributor == @servername. This is used by UI
  12782.     ** before installing a distributor.
  12783.     */
  12784.     if @distributor = @@servername
  12785.         select @distributor_rpc = @@servername
  12786.     else
  12787.     begin
  12788.         EXEC @return_status = dbo.sp_helpdistributor @rpcsrvname = @distributor_rpc OUTPUT
  12789.         IF @@error <> 0 OR @return_status <> 0 OR @distributor_rpc IS NULL
  12790.         BEGIN
  12791.             RAISERROR (20036, 16, -1)
  12792.             RETURN (1)
  12793.         END
  12794.     end
  12795.  
  12796.     declare @key_exists int
  12797.     select @key_exists = 0
  12798.     create table #keyexists (keyexists int) 
  12799.     select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regread'
  12800.     insert into #keyexists exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver'
  12801.     select @key_exists = keyexists from #keyexists
  12802.     if (@key_exists = 1)
  12803.         begin
  12804.             select @distproc = RTRIM(@distributor_rpc) + '.master..xp_regenumvalues'
  12805.             exec @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver'    
  12806.             if @@ERROR<>0 return (1)
  12807.         end
  12808.     drop table #keyexists
  12809.     RETURN (0)
  12810. GO
  12811. exec dbo.sp_MS_marksystemobject sp_enumcustomresolvers
  12812. go
  12813.  
  12814. grant execute on dbo.sp_enumcustomresolvers to public
  12815. go
  12816.  
  12817. raiserror('Creating procedure sp_changemergefilter', 0,1)
  12818. GO
  12819.  
  12820. create procedure sp_changemergefilter(
  12821.     @publication            sysname,
  12822.     @article                sysname,
  12823.     @filtername             sysname,
  12824.     @property               sysname,
  12825.     @value                  nvarchar(2000),
  12826.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  12827.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  12828.     )AS
  12829.  
  12830.     set nocount on
  12831.  
  12832.     declare @pre_command        int
  12833.     declare @qual_object        nvarchar(132)
  12834.     declare @qual_join_object    nvarchar(132)
  12835.     declare @join_articlename    nvarchar(4000)
  12836.     declare @db_name        sysname
  12837.     declare @pubid          uniqueidentifier
  12838.     declare @artid          uniqueidentifier
  12839.     declare @object            sysname
  12840.     declare @join_object    sysname
  12841.     declare @retcode        int
  12842.     declare @join_filterid  int
  12843.     declare @join_objid     int
  12844.     declare @join_nickname  int
  12845.     declare @snapshot_ready int
  12846.  
  12847.     /*
  12848.     ** Security Check.
  12849.     ** Only the System Administrator (SA) or the Database Owner (dbo) can
  12850.     ** call this procedure
  12851.     */
  12852.     exec @retcode = dbo.sp_MSreplcheck_publish
  12853.     if @@ERROR <> 0 or @retcode <> 0
  12854.         return(1)
  12855.  
  12856.     /*
  12857.     ** Parameter Check: @join_articlename.
  12858.     ** The join_articlename cannot be NULL 
  12859.     */
  12860.     if @filtername is NULL
  12861.         begin
  12862.             raiserror (14043, 11, -1, '@filtername')
  12863.             return (1)
  12864.         end
  12865.  
  12866.     if @value is NULL or @value = ''
  12867.         begin
  12868.             raiserror (14043, 11, -1, '@value')
  12869.             return (1)
  12870.         end
  12871.  
  12872.     /*
  12873.     ** Parameter Check: @publication.
  12874.     ** The @publication id cannot be NULL and must conform to the rules
  12875.     ** for identifiers.
  12876.     */
  12877.     if @publication is NULL
  12878.         begin
  12879.             raiserror (14043, 11, -1, '@publication')
  12880.             return (1)
  12881.         end
  12882.     /*
  12883.     ** Get the pubid and make sure the publication exists
  12884.     */
  12885.     select @pubid = pubid, @snapshot_ready=snapshot_ready from sysmergepublications where 
  12886.         name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  12887.     if @pubid is NULL
  12888.         begin
  12889.             raiserror (20026, 16, -1, @publication)
  12890.             return (1)
  12891.         end
  12892.  
  12893.     select @db_name = db_name from sysmergesubscriptions
  12894.         where (pubid=@pubid) and (subid=@pubid)
  12895.         IF @db_name <> db_name()
  12896.         BEGIN
  12897.             RAISERROR (20047, 16, -1)
  12898.             RETURN (1)
  12899.         END
  12900.  
  12901.     /*
  12902.     ** Parameter Check: @article.
  12903.     ** Check to see that the @article is valid and does exist 
  12904.     */
  12905.     if @article is NULL
  12906.         begin
  12907.             raiserror (20045, 16, -1)
  12908.             return (1)
  12909.         end
  12910.         
  12911.     select @artid = artid, @object=object_name(objid), @pre_command=pre_creation_command from sysmergearticles where name = @article and pubid = @pubid  
  12912.     if @artid is NULL
  12913.         begin
  12914.             raiserror (20046, 16, -1)
  12915.             return (1)
  12916.         end
  12917.  
  12918.     
  12919.     select @join_filterid=join_filterid, @join_articlename=join_articlename from sysmergesubsetfilters
  12920.         where pubid=@pubid and artid=@artid and filtername=@filtername
  12921.  
  12922.     if @join_filterid is null
  12923.         begin
  12924.             raiserror (21362, 16, -1, @filtername) 
  12925.             return (1)
  12926.         end
  12927.  
  12928.      IF @property IS NULL
  12929.         BEGIN
  12930.             CREATE TABLE #temp (properties sysname collate database_default)
  12931.             INSERT INTO #temp VALUES ('filtername')
  12932.             INSERT INTO #temp VALUES ('join_filterclause')
  12933.             INSERT INTO #temp VALUES ('join_articlename')
  12934.             INSERT INTO #temp VALUES ('join_unique_key')
  12935.             select * FROM #tab1
  12936.             RETURN (0)
  12937.         END 
  12938.  
  12939.  
  12940.     if @value is null
  12941.         begin
  12942.             RAISERROR (14043, 16, -1, @property)
  12943.             return (1)
  12944.         end
  12945.  
  12946.     begin TRAN
  12947.     save TRAN change_filter
  12948.  
  12949.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('join_filterclause','join_articlename','join_unique_key')
  12950.         and @snapshot_ready>0
  12951.     begin
  12952.             -- 1 means'drop': which is the only option that support reintialization
  12953.             if @pre_command<>1                 
  12954.                 begin
  12955.                     raiserror(21419, 16, -1, @filtername, @article)
  12956.                     goto FAILURE            
  12957.                 end
  12958.             /*
  12959.             ** make sure we know we really want to do this.
  12960.             */
  12961.             if @force_invalidate_snapshot = 0
  12962.                 begin
  12963.                     raiserror(20607, 16, -1)
  12964.                     goto FAILURE
  12965.                 end
  12966.             if @force_reinit_subscription = 0
  12967.                 begin
  12968.                     raiserror(20608, 16, -1)
  12969.                     goto FAILURE
  12970.                 end
  12971.  
  12972.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  12973.             if @@ERROR<>0
  12974.                 goto FAILURE
  12975.             exec @retcode = sp_MSreinitmergepublication @publication
  12976.             if @retcode<>0 or @@ERROR<>0
  12977.                 goto FAILURE
  12978.  
  12979.     end
  12980.     
  12981.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='join_filterclause'
  12982.         BEGIN
  12983.         /* check the validity of join_filterclause */
  12984.         select @join_object=object_name(objid) from sysmergearticles where name=@join_articlename and pubid=@pubid
  12985.         select @qual_object=QUOTENAME(@object)
  12986.         select @qual_join_object=QUOTENAME(@join_object)
  12987.         exec ('declare @test int select @test=1 from ' + @qual_object + ', ' + @qual_join_object + ' where ' + @value)
  12988.         if @@ERROR<>0
  12989.             begin
  12990.                 raiserror(21256, 16, -1, @value, @object)
  12991.                 goto FAILURE
  12992.             end
  12993.         update sysmergesubsetfilters set join_filterclause=@value
  12994.                 where join_filterid=@join_filterid
  12995.         execute @retcode = dbo.sp_MSsubsetpublication @publication
  12996.         if @@ERROR <> 0 or @retcode<>0
  12997.             goto FAILURE
  12998.         END
  12999.  
  13000.        IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='join_unique_key'
  13001.         BEGIN
  13002.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false')
  13003.                 BEGIN
  13004.                       RAISERROR(14137,16,-1)
  13005.                       RETURN(1)
  13006.                  END
  13007.             if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  13008.                 update sysmergesubsetfilters set join_unique_key=1 where join_filterid=@join_filterid
  13009.             else
  13010.                 update sysmergesubsetfilters set join_unique_key=0 where join_filterid=@join_filterid
  13011.             if @@ERROR <> 0 or @retcode<>0
  13012.                 goto FAILURE
  13013.         END
  13014.  
  13015.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='filtername'
  13016.         BEGIN
  13017.             update sysmergesubsetfilters set filtername=@value
  13018.                 where join_filterid=@join_filterid
  13019.             if @@ERROR<>0
  13020.                 goto FAILURE
  13021.         END
  13022.  
  13023.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)='join_articlename'
  13024.         BEGIN
  13025.             select @join_objid = objid from sysmergearticles where name = @value and pubid = @pubid
  13026.             
  13027.             IF @join_objid is NULL
  13028.             BEGIN
  13029.                 raiserror (14027, 11, -1, @value)
  13030.                 goto FAILURE
  13031.             END
  13032.  
  13033.             select @join_nickname = nickname from sysmergearticles where pubid = @pubid AND objid = @join_objid 
  13034.             if @join_nickname is NULL
  13035.             begin
  13036.                 raiserror (20001, 11, -1, @article, @publication)
  13037.                 goto FAILURE
  13038.             end
  13039.             
  13040.             update sysmergesubsetfilters set join_articlename=@value, join_nickname=@join_nickname
  13041.                 where join_filterid=@join_filterid
  13042.             if @@ERROR<>0
  13043.                 goto FAILURE
  13044.         END
  13045.         
  13046.     Commit TRAN
  13047.     return(0)
  13048.  
  13049. FAILURE:
  13050.     if @@TRANCOUNT > 0
  13051.     begin
  13052.         ROLLBACK TRANSACTION change_filter
  13053.         COMMIT TRANSACTION
  13054.     end
  13055.     RAISERROR (20038, 16, -1, @article, @publication)
  13056.     return(1)
  13057.  
  13058. go
  13059. exec dbo.sp_MS_marksystemobject sp_changemergefilter
  13060. go
  13061.  
  13062. grant execute on dbo.sp_changemergefilter to public
  13063. go
  13064.  
  13065. raiserror('Creating procedure sp_addmergefilter', 0,1)
  13066. GO
  13067.  
  13068. create procedure sp_addmergefilter(
  13069.     @publication            sysname,            /* publication name */
  13070.     @article                sysname,            /* article name */
  13071.     @filtername             sysname,            /* join filter name */
  13072.     @join_articlename       sysname,            /* Name of the table being joined to the base table */
  13073.     @join_filterclause      nvarchar(2000),     /* filter clause qualifying the join */             
  13074.     @join_unique_key        int = 0,
  13075.     @force_invalidate_snapshot bit = 0,            /* Force invalidate existing snapshot */
  13076.     @force_reinit_subscription bit = 0            /* Force reinit subscription */
  13077.     )AS
  13078.  
  13079.     set nocount on
  13080.  
  13081.     /*
  13082.     ** Declarations.
  13083.     */
  13084.     declare @snapshot_ready        int
  13085.     declare @db_name            sysname
  13086.     declare @pubid              uniqueidentifier                
  13087.     declare @artid              uniqueidentifier
  13088.     declare @art_nickname       int
  13089.     declare @join_nickname      int
  13090.     declare @db                 sysname
  13091.     declare @qual_object        nvarchar(150)
  13092.     declare @qual_join_object    nvarchar(150)
  13093.     declare @qual_object_view    nvarchar(150)
  13094.     declare @qual_join_object_view nvarchar(150)
  13095.     
  13096.     declare @object             sysname
  13097.     declare @vertical            int
  13098.     declare @join_vertical        int
  13099.     declare @join_object        nvarchar(140)
  13100.     declare @object_view        nvarchar(140)
  13101.     declare @join_object_view    nvarchar(140)
  13102.     declare @owner              sysname
  13103.     declare @retcode            int
  13104.     declare @join_objid         int
  13105.     declare @objid                int
  13106.     declare @status             int
  13107.     declare @column_list        nvarchar(4000)
  13108.     
  13109.     /* make sure current database is enabled for merge replication */
  13110.     exec @retcode=dbo.sp_MSCheckmergereplication
  13111.     if @@ERROR<>0 or @retcode<>0
  13112.         return (1)
  13113.  
  13114.     /*
  13115.     ** Security Check.
  13116.     ** Only the System Administrator (SA) or the Database Owner (dbo) can
  13117.     ** add an article to a publication.
  13118.     */
  13119.     exec @retcode = dbo.sp_MSreplcheck_publish
  13120.     if @@ERROR <> 0 or @retcode <> 0
  13121.         return(1)
  13122.  
  13123.     /*
  13124.     ** Parameter Check: @filtername.
  13125.     ** The join_filter_name cannot be NULL 
  13126.     */
  13127.     if @filtername is NULL
  13128.         begin
  13129.             raiserror (14043, 11, -1, @filtername)
  13130.             return (1)
  13131.         end
  13132.  
  13133.     if @join_filterclause is NULL or @join_filterclause = ''
  13134.         begin
  13135.             raiserror (14043, 11, -1, '@join_filterclause')
  13136.             return (1)
  13137.         end
  13138.  
  13139.     /*
  13140.     ** Parameter Check: @publication.
  13141.     ** The @publication id cannot be NULL and must conform to the rules
  13142.     ** for identifiers.
  13143.     */
  13144.     if @publication is NULL
  13145.         begin
  13146.             raiserror (14003, 16, -1)
  13147.             return (1)
  13148.         end
  13149.  
  13150.     
  13151.     /*
  13152.     ** Get the pubid and make sure the publication exists
  13153.     */
  13154.     select @pubid = pubid, @snapshot_ready=snapshot_ready from sysmergepublications 
  13155.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13156.     if @pubid is NULL
  13157.         begin
  13158.             raiserror (20026, 16, -1, @publication)
  13159.             return (1)
  13160.         end
  13161.  
  13162.     if @snapshot_ready>0
  13163.         begin
  13164.             /*
  13165.             ** make sure we know we really want to do this.
  13166.             */
  13167.             if @force_invalidate_snapshot = 0
  13168.                 begin
  13169.                     raiserror(21366, 16, -1, @filtername)
  13170.                     goto FAILURE
  13171.                 end
  13172.             if @force_reinit_subscription = 0
  13173.                 begin
  13174.                     raiserror(21367, 16, -1, @filtername)
  13175.                     goto FAILURE
  13176.                 end
  13177.  
  13178.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  13179.             if @@ERROR<>0
  13180.                 goto FAILURE
  13181.             exec @retcode = sp_MSreinitmergepublication @publication
  13182.             if @retcode<>0 or @@ERROR<>0
  13183.                 goto FAILURE
  13184.  
  13185.         end
  13186.  
  13187.     select @db_name = db_name from sysmergesubscriptions
  13188.         where (pubid=@pubid) and (subid=@pubid) 
  13189.         IF @db_name <> db_name()
  13190.         BEGIN
  13191.             RAISERROR (20047, 16, -1)
  13192.             RETURN (1)
  13193.         END        
  13194.     /*
  13195.     ** Parameter Check: @article.
  13196.     ** Check to see that the @article is valid and does exist 
  13197.     */
  13198.     if @article is NULL
  13199.         begin
  13200.             raiserror (20045, 16, -1)
  13201.             return (1)
  13202.         end
  13203.         
  13204.     select @artid = artid, @objid=objid, @vertical=vertical_partition, @art_nickname = nickname from sysmergearticles where name = @article and pubid = @pubid  
  13205.     if @artid is NULL
  13206.         begin
  13207.             raiserror (20046, 16, -1)
  13208.             return (1)
  13209.         end
  13210.         
  13211.     /*
  13212.     **  Get the id of the @join_articlename
  13213.     */
  13214.     select @join_objid = objid, @join_vertical= vertical_partition from sysmergearticles where name=@join_articlename and pubid = @pubid
  13215.     
  13216.     IF @join_objid is NULL
  13217.         BEGIN
  13218.             raiserror (14027, 11, -1, @join_articlename)
  13219.             return (1)
  13220.         END
  13221.         
  13222.     /* check the validity of join_filterclause */
  13223.     select @object = object_name(@objid)
  13224.  
  13225.     select @join_object = object_name(@join_objid)
  13226.     
  13227.     select @object_view = @object
  13228.     select @join_object_view = @join_object
  13229.             
  13230.     /* is current article vertically partitioned */
  13231.     if @vertical=1
  13232.     begin
  13233.           select @object_view = 'OBJECT_VIEW_' + @object
  13234.  
  13235.           select @qual_object_view=QUOTENAME(@object_view)
  13236.           select @qual_object=QUOTENAME(@object)
  13237.           
  13238.           exec @retcode = sp_MSgetcolumnlist @pubid, @column_list OUTPUT, @objid
  13239.           exec ('create view ' + @qual_object_view + ' as select ' + @column_list + ' from ' + @qual_object)
  13240.           if @@ERROR<>0
  13241.               goto FAILURE
  13242.           
  13243.     end
  13244.  
  13245.     /* is join article vertically partitioned */
  13246.     if @join_vertical=1
  13247.     begin
  13248.           select @join_object_view = 'JOIN_OBJECT_VIEW_' + @join_object
  13249.           select @qual_join_object_view = QUOTENAME(@join_object_view)
  13250.           select @qual_join_object=QUOTENAME(@join_object)
  13251.           
  13252.           exec @retcode = sp_MSgetcolumnlist @pubid, @column_list OUTPUT, @join_objid
  13253.           exec ('create view ' + @qual_join_object_view + ' as select ' + @column_list + ' from ' + @qual_join_object)
  13254.           if @@ERROR<>0
  13255.               goto FAILURE
  13256.          
  13257.     end
  13258.  
  13259.     select @qual_object_view=QUOTENAME(@object_view)
  13260.     select @qual_join_object_view = QUOTENAME(@join_object_view)
  13261.     select @qual_join_object=QUOTENAME(@join_object)
  13262.     select @qual_object=QUOTENAME(@object)
  13263.  
  13264.     exec ('declare @test int select @test=1 from ' + @qual_object_view + ' ' + @qual_object + ', ' + @qual_join_object_view + ' ' + @qual_join_object + ' where ' + @join_filterclause)
  13265.     if @@ERROR<>0
  13266.         begin
  13267.             if @vertical=1
  13268.                 exec ('drop view ' + @qual_object_view)
  13269.             if @join_vertical=1
  13270.                  exec ('drop view ' + @qual_join_object_view)
  13271.             raiserror(21256, 16, -1, @join_filterclause, @article)
  13272.             return (1)
  13273.         end
  13274.         
  13275.     if @vertical=1
  13276.         exec ('drop view ' + @qual_object_view)
  13277.     if @join_vertical=1
  13278.          exec ('drop view ' + @qual_join_object_view)
  13279.     
  13280.     select @join_nickname = nickname from sysmergearticles where pubid = @pubid AND objid = @join_objid 
  13281.     if @join_nickname is NULL
  13282.         begin
  13283.             raiserror (20001, 11, -1, @article, @publication)
  13284.             return (1)
  13285.         end
  13286.  
  13287.     IF NOT EXISTS (select * from sysmergearticles where pubid=@pubid AND nickname = @join_nickname)
  13288.         BEGIN
  13289.             RAISERROR (20046, 16, -1) /* Only the original publisher can do so */
  13290.             RETURN (1)
  13291.         END
  13292.     
  13293.     /*
  13294.     ** Make sure that the table name specified is a table and not a view.
  13295.     */
  13296.     
  13297.     if NOT exists (select * from sysobjects
  13298.         where id = @join_objid AND type = 'U')
  13299.         begin
  13300.             raiserror (14028, 16, -1)
  13301.             return (1)
  13302.         end
  13303.  
  13304.     /*
  13305.     **  Add the join filter to sysmergesubsetfilters if it is not already there
  13306.     */
  13307.  
  13308.     IF exists (select * from sysmergesubsetfilters 
  13309.     where filtername=@filtername and  pubid=@pubid and artid=@artid) 
  13310.         begin
  13311.             raiserror (20002, 16, -1, @filtername, @article, @publication)
  13312.             return (1)
  13313.         end
  13314.     
  13315.     insert INTO sysmergesubsetfilters(filtername, pubid, artid, art_nickname, join_articlename, join_nickname, join_unique_key, join_filterclause)
  13316.         values(@filtername, @pubid, @artid, @art_nickname, @join_articlename, @join_nickname, @join_unique_key, @join_filterclause)                 
  13317.     if @@error <> 0
  13318.         begin
  13319.             goto FAILURE
  13320.         end
  13321.     execute @retcode = dbo.sp_MSsubsetpublication @publication
  13322.     if @@ERROR <> 0 or @retcode <>0
  13323.         goto FAILURE
  13324.     
  13325.     return (0)
  13326.     
  13327. FAILURE:
  13328.     RAISERROR (20038, 16, -1, @article, @publication)
  13329.     return (1)
  13330.  
  13331. go
  13332. exec dbo.sp_MS_marksystemobject sp_addmergefilter
  13333. go
  13334.  
  13335. grant execute on dbo.sp_addmergefilter to public
  13336. go
  13337.  
  13338. raiserror('Creating procedure sp_dropmergefilter', 0,1)
  13339. GO
  13340.  
  13341. create procedure sp_dropmergefilter
  13342.     @publication            sysname,            /* publication name */
  13343.     @article                sysname,            /* article name */
  13344.     @filtername             sysname,             /* Name of the table being joined to the base table */
  13345.     @force_invalidate_snapshot bit = 0
  13346.     AS
  13347.  
  13348.     set nocount on
  13349.  
  13350.     /*
  13351.     ** Declarations.
  13352.     */
  13353.     declare @pubid                  uniqueidentifier                
  13354.     declare @artid                  uniqueidentifier
  13355.     declare @join_objid             int
  13356.     declare @retcode                int
  13357.     declare @join_filterid          int
  13358.     declare @db_name                sysname
  13359.     declare @allow_anonymous        int
  13360.     declare @snapshot_ready            tinyint
  13361.  
  13362.     /* make sure current database is enabled for merge replication */
  13363.     exec @retcode=dbo.sp_MSCheckmergereplication
  13364.     if @@ERROR<>0 or @retcode<>0
  13365.         return (1)
  13366.  
  13367.     /* 
  13368.     ** Security Check.
  13369.     */
  13370.     exec @retcode=sp_MSreplcheck_publish
  13371.     if @@ERROR <> 0 or @retcode <> 0
  13372.         return (1)
  13373.  
  13374.     /*
  13375.     ** Parameter Check: @publication.
  13376.     ** The @publication id cannot be NULL and must conform to the rules
  13377.     ** for identifiers.
  13378.     */
  13379.     
  13380.     if @publication is NULL
  13381.         begin
  13382.             raiserror (14003, 16, -1)
  13383.             return (1)
  13384.         end
  13385.  
  13386.     /*
  13387.     ** Get the pubid, and check if this publication exists.
  13388.     */
  13389.     select @pubid = pubid, @snapshot_ready=snapshot_ready, @allow_anonymous=allow_anonymous from sysmergepublications 
  13390.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13391.     if @pubid is NULL
  13392.         begin
  13393.             raiserror (20026, 16, -1, @publication )
  13394.             return (1)
  13395.         end
  13396.  
  13397.     select @db_name = db_name from sysmergesubscriptions
  13398.         where (pubid=@pubid) and (subid=@pubid) 
  13399.         IF @db_name <> db_name()
  13400.         BEGIN
  13401.             RAISERROR (20047, 16, -1)
  13402.             RETURN (1)
  13403.         END
  13404.     
  13405.     /*
  13406.     ** Parameter Check: @article.
  13407.     ** Check to see that the @article is valid, and if it exists
  13408.     */
  13409.     if @article is NULL
  13410.         begin
  13411.             raiserror (20045, 16, -1)
  13412.             return (1)
  13413.         end
  13414.  
  13415.     if @snapshot_ready>0 and (@allow_anonymous=1 or 
  13416.         exists (select * from sysmergesubscriptions where pubid=@pubid and subid<>pubid and status=1))
  13417.         BEGIN
  13418.             RAISERROR (21372, 16, -1, @filtername, @publication)
  13419.             RETURN (1)
  13420.         END
  13421.  
  13422.      if @snapshot_ready>0
  13423.         begin
  13424.             if @force_invalidate_snapshot = 0
  13425.                 begin
  13426.                     raiserror(21382, 16, -1, @filtername)
  13427.                     return (1)
  13428.                 end
  13429.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  13430.             if @@ERROR<>0
  13431.                 return (1)
  13432.         end
  13433.    
  13434.        
  13435.     select @artid = artid from sysmergearticles where name = @article and pubid = @pubid  
  13436.     if @artid is NULL
  13437.         begin
  13438.             raiserror (20046, 16, -1)
  13439.             return (1)
  13440.         end
  13441.     
  13442.  
  13443.     select @join_filterid = join_filterid from sysmergesubsetfilters
  13444.         where pubid = @pubid AND artid= @artid AND filtername=@filtername  
  13445.     
  13446.     /*
  13447.     **  Remove the join filter from sysmergesubsetfilters
  13448.     */
  13449.     delete from sysmergesubsetfilters
  13450.         where join_filterid = @join_filterid
  13451.     if @@error <> 0
  13452.         begin
  13453.             goto FAILURE
  13454.         end
  13455.  
  13456.     /*
  13457.     ** set the pub type to subset or full as appropriate
  13458.     */
  13459.     exec @retcode=sp_MSsubsetpublication @publication
  13460.     if @@ERROR <> 0 or @retcode<>0
  13461.         begin
  13462.             goto FAILURE
  13463.         end
  13464.  
  13465.     return(0)
  13466. FAILURE:
  13467.     RAISERROR (20039, 16, -1, @article, @publication)
  13468.     return (1)
  13469. go
  13470.  
  13471. exec dbo.sp_MS_marksystemobject sp_dropmergefilter
  13472. go
  13473.  
  13474. raiserror('Creating procedure sp_helpmergefilter', 0,1)
  13475. GO
  13476.  
  13477. create procedure sp_helpmergefilter
  13478.     @publication            sysname,        /* publication name */
  13479.     @article                sysname = '%',          /* article name */ 
  13480.     @filtername             sysname = '%'
  13481.     AS
  13482.  
  13483.     set nocount on
  13484.  
  13485.     /*
  13486.     ** Declarations.
  13487.     */
  13488.     declare @pubid                  uniqueidentifier                
  13489.     declare @artid                  uniqueidentifier
  13490.     declare @retcode                int
  13491.  
  13492.     /* 
  13493.     ** No security checking is needed for sp_help??
  13494.     */
  13495.  
  13496.  
  13497.     /*
  13498.     **  Calling sp_help* is all right whether current database is enabled for pub/sub or not
  13499.     */
  13500.     IF not exists (select * from sysobjects where name='sysmergesubscriptions')
  13501.         RETURN (0)
  13502.         
  13503.     /*
  13504.     ** Parameter Check: @publication.
  13505.     ** The @publication id cannot be NULL and must conform to the rules
  13506.     ** for identifiers.
  13507.     */
  13508.     if @publication is NULL
  13509.         begin
  13510.             raiserror (14003, 16, -1)
  13511.             return (1)
  13512.         end
  13513.     /*
  13514.     ** Get the pubid and check if the publication does exist
  13515.     */
  13516.     select @pubid = pubid from sysmergepublications 
  13517.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13518.     if @pubid is NULL
  13519.         begin
  13520.             raiserror (20026, 16, -1, @publication)
  13521.             return (1)
  13522.         end
  13523.  
  13524.     /*
  13525.     ** Parameter Check: @article.
  13526.     ** If an @article is specified, make sure it exists
  13527.     */
  13528.     select @artid = artid from sysmergeextendedarticlesview where name = @article and pubid = @pubid  
  13529.     if @artid is NULL and (@article <> '%' or @filtername <> '%')
  13530.         begin
  13531.             raiserror (20046, 16, -1)
  13532.             return (1)
  13533.         end
  13534.  
  13535.     /*
  13536.     **  Return the join filters from sysmergesubsetfilters
  13537.     */
  13538.  
  13539. IF @filtername <> '%'
  13540.     select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
  13541.             'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
  13542.             'article name' = b_a.name
  13543.         from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
  13544.             sysusers b_u, sysmergeextendedarticlesview j_a, sysmergeextendedarticlesview b_a
  13545.         where   f.pubid = @pubid AND b_a.pubid = @pubid
  13546.             AND f.filtername = @filtername
  13547.             AND f.artid = @artid 
  13548.             AND f.artid = b_a.artid AND b_o.id = b_a.objid
  13549.             AND b_u.uid = b_o.uid
  13550.             AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
  13551.             AND j_u.uid = j_o.uid
  13552.            ORDER BY j_o.name, b_o.name
  13553.  ELSE
  13554.     begin
  13555.     if @artid is not null
  13556.     select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
  13557.             'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
  13558.             'article name' = b_a.name
  13559.         from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
  13560.             sysusers b_u, sysmergeextendedarticlesview j_a, sysmergeextendedarticlesview b_a
  13561.         where   f.pubid = @pubid AND b_a.pubid = @pubid
  13562.             AND f.artid = @artid 
  13563.             AND f.artid = b_a.artid AND b_o.id = b_a.objid
  13564.             AND b_u.uid = b_o.uid
  13565.             AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
  13566.             AND j_u.uid = j_o.uid
  13567.            ORDER BY j_o.name, b_o.name
  13568.     else
  13569.     select distinct join_filterid, filtername, 'join article name' = j_a.name, join_filterclause, f.join_unique_key,
  13570.             'base table owner' = b_u.name, 'base table name' = b_o.name, 'join table owner' = j_u.name, 'join table name' = j_o.name,
  13571.             'article name' = b_a.name
  13572.         from sysmergesubsetfilters f, sysobjects j_o, sysobjects b_o, sysusers j_u,
  13573.             sysusers b_u, sysmergeextendedarticlesview j_a, sysmergeextendedarticlesview b_a
  13574.         where   f.pubid = @pubid AND b_a.pubid = @pubid
  13575.             AND f.artid = b_a.artid AND b_o.id = b_a.objid
  13576.             AND b_u.uid = b_o.uid
  13577.             AND f.join_nickname = j_a.nickname AND j_o.id = j_a.objid and j_a.pubid = @pubid
  13578.             AND j_u.uid = j_o.uid
  13579.            ORDER BY j_o.name, b_o.name
  13580.     end
  13581.     return(0)
  13582. go
  13583. exec dbo.sp_MS_marksystemobject sp_helpmergefilter
  13584. go
  13585.  
  13586. grant execute on dbo.sp_helpmergefilter to public
  13587. go
  13588.  
  13589. raiserror('Creating procedure sp_MSscript_dri', 0,1)
  13590. go
  13591. create procedure sp_MSscript_dri
  13592.     (@publication   sysname, 
  13593.     @article        sysname)
  13594. AS
  13595.  
  13596. declare @pubid  uniqueidentifier
  13597.     
  13598. select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13599.         
  13600. select rkeyid, fkeyid from sysreferences 
  13601.         where fkeyid in (select objid from sysmergearticles where pubid = @pubid and name = @article) 
  13602.             and rkeyid not in (select objid from sysmergearticles   where pubid = @pubid)
  13603. go
  13604. exec dbo.sp_MS_marksystemobject sp_MSscript_dri
  13605. go
  13606. grant execute on dbo.sp_MSscript_dri to public
  13607. go
  13608.  
  13609.  
  13610. raiserror('Creating procedure sp_MSenumpubreferences', 0,1)
  13611. GO
  13612. create procedure sp_MSenumpubreferences (@publication sysname)
  13613. as
  13614.     declare @pubid uniqueidentifier
  13615.     declare @retcode int
  13616.     
  13617.     /* 
  13618.     ** Security Check.
  13619.     */
  13620.     exec @retcode = dbo.sp_MSreplcheck_publish
  13621.     if @@ERROR <> 0 or @retcode <> 0
  13622.         return(1)
  13623.  
  13624.     /* make sure current database is enabled for merge replication */
  13625.     exec @retcode=dbo.sp_MSCheckmergereplication
  13626.     if @@ERROR<>0 or @retcode<>0
  13627.         return (1)
  13628.  
  13629.     select @pubid = pubid from sysmergepublications where
  13630.         name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13631.     if @pubid is null
  13632.         BEGIN
  13633.             RAISERROR (20026, 16, -1, @publication)
  13634.             RETURN (1)
  13635.         END
  13636.     select distinct ReferencingObject = object_name(rkeyid), ArticleObject  = object_name(fkeyid) 
  13637.         from sysreferences r, sysmergearticles
  13638.         where r.fkeyid in (select objid from sysmergearticles where pubid = @pubid) 
  13639.             and r.rkeyid not in (select objid from sysmergearticles where pubid = @pubid)
  13640.  
  13641.     select distinct ReferencedObject = object_name(fkeyid), ArticleObject = object_name(rkeyid) from sysreferences r
  13642.         where r.rkeyid in (select objid from sysmergearticles
  13643.             where pubid = @pubid) and
  13644.         r.fkeyid not in (select objid from sysmergearticles
  13645.             where pubid = @pubid)           
  13646.     return (0)
  13647. go
  13648.  
  13649. exec dbo.sp_MS_marksystemobject sp_MSenumpubreferences
  13650. go
  13651.  
  13652. grant execute on dbo.sp_MSenumpubreferences to public
  13653. go
  13654.  
  13655. raiserror('Creating procedure sp_MSsubsetpublication', 0,1)
  13656. GO
  13657.  
  13658. create procedure sp_MSsubsetpublication (@publication sysname)
  13659. as
  13660.     declare @pubid          uniqueidentifier
  13661.     declare @false          bit
  13662.     declare @true           bit
  13663.     declare @boolean_filter bit
  13664.     declare @join_filter    bit
  13665.     declare @full           int
  13666.     declare @subset         int
  13667.     declare @unsynced       int
  13668.  
  13669.     /*
  13670.     ** Initializations
  13671.     */
  13672.     select @true        = 1
  13673.     select @false       = 0
  13674.     select @full        = 0     /* Const: publication type 'full' */
  13675.     select @subset      = 1     /* Const: publication type 'subset' */
  13676.     select @unsynced    = 1
  13677.     
  13678.     if not exists (select * from sysobjects where name = 'sysmergepublications')
  13679.         BEGIN
  13680.             RAISERROR (20054, 16, -1)
  13681.             RETURN (1)
  13682.         END 
  13683.  
  13684.     select @pubid = pubid from sysmergepublications where
  13685.         name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13686.     if @pubid is null
  13687.         BEGIN
  13688.             RAISERROR (20026, 16, -1, @publication)
  13689.             RETURN (1)
  13690.         END
  13691.  
  13692.     /* 
  13693.     ** Set the publication_type to subset if the publication has either a boolean or a join filter
  13694.     */
  13695.     if exists (select * from sysmergearticles where pubid = @pubid and len(subset_filterclause) > 0)
  13696.         set @boolean_filter = @true
  13697.     if exists (select * from sysmergesubsetfilters where pubid = @pubid)
  13698.         set @join_filter = @true
  13699.  
  13700.     /*
  13701.     ** For subset publications set the article status to be unsynced so that the triggers can be regenerated.
  13702.     */
  13703.     if (@boolean_filter = 1 OR @join_filter = 1)        
  13704.         begin
  13705.             update sysmergepublications set publication_type = @subset where pubid = @pubid
  13706.             if @@ERROR <> 0 return (1)
  13707.             update sysmergearticles set status = @unsynced where pubid = @pubid
  13708.             if @@ERROR <> 0 return (1)
  13709.         end         
  13710.     else
  13711.         update sysmergepublications set publication_type = @full where pubid = @pubid               
  13712.     if @@ERROR <> 0 return (1)
  13713.         
  13714.     return(0)           
  13715. go
  13716.  
  13717. exec dbo.sp_MS_marksystemobject sp_MSsubsetpublication
  13718. go
  13719. raiserror('Creating procedure sp_MSindexcolfrombin', 0,1)
  13720. GO
  13721.  
  13722. create procedure sp_MSindexcolfrombin
  13723.     @object_id      int,
  13724.     @col_index      int,
  13725.     @colids_bin     varbinary(256),
  13726.     @colname        sysname output,
  13727.     @columns        varbinary(128) = NULL
  13728.     AS
  13729.     /* Declare variables */
  13730.     declare @start_byte int
  13731.     declare @colid int
  13732.     declare @retcode int
  13733.     set @colid = unicode( substring( convert( nvarchar(128),@colids_bin ), @col_index, 1 ) )
  13734.     select @colname = QUOTENAME(name) from syscolumns where id = @object_id and colid = @colid
  13735.  
  13736.     /* vertical partitioning is ON */
  13737.     if @columns is not NULL
  13738.     begin
  13739.         /* see if this column is currently in the vertical partitioning */
  13740.         exec @retcode = sp_MStestbit @bm=@columns, @coltotest=@colid
  13741.         if @retcode=0
  13742.             select @colname = NULL
  13743.     end
  13744.     return (0)
  13745. GO
  13746. exec dbo.sp_MS_marksystemobject sp_MSindexcolfrombin
  13747. go
  13748.  
  13749. raiserror('Creating procedure sp_MSmakejoinfilter', 0,1)
  13750. GO
  13751.  
  13752. create procedure sp_MSmakejoinfilter
  13753.     @publication    sysname,
  13754.     @article        sysname,
  13755.     @base_objid     int,
  13756.     @join_objid     int,
  13757.     @join_unique    int
  13758.     AS
  13759.  
  13760.     /* Declare additional variables */
  13761.     declare     @table_name nvarchar(140)
  13762.     declare     @join_table nvarchar(140)
  13763.     declare     @join_article sysname
  13764.     declare     @filt_name  sysname
  13765.     declare     @basecol    sysname
  13766.     declare     @joincol    sysname
  13767.     declare     @keycnt     int
  13768.     declare     @basekeys   varbinary(32)
  13769.     declare     @joinkeys   varbinary(32)
  13770.     declare     @base_columns    varbinary(128)
  13771.     declare     @join_columns    varbinary(128)
  13772.     declare     @keyindex   int
  13773.     declare     @filtclause nvarchar(3000)
  13774.     declare     @filtpiece  nvarchar(500)
  13775.     declare     @qual_jointable nvarchar(270)
  13776.     declare     @retcode    smallint
  13777.     declare     @pubid      uniqueidentifier
  13778.     declare     @first_piece bit
  13779.  
  13780.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  13781.  
  13782.     select @base_columns=0x00 -- so that no base column name will be returned if following query does not find a match
  13783.     select @join_columns=0x00 -- same as above
  13784.     
  13785.     select @base_columns=columns from sysmergearticles where pubid=@pubid and objid=@base_objid
  13786.     select @join_columns=columns from sysmergearticles where pubid=@pubid and objid=@join_objid
  13787.     
  13788.     /* Are we adding join filter on referencing table (@join_unique = 1) or on unique key table ? */
  13789.     if @join_unique = 1
  13790.     /* Select the keycnt, fkeys, rkeys, and filter name from sysreferences */
  13791.         select @keycnt = keycnt, @basekeys = forkeys, @joinkeys = refkeys, @filt_name = object_name(constid)
  13792.             from sysreferences where fkeyid = @base_objid and rkeyid = @join_objid
  13793.     else
  13794.         select @keycnt = keycnt, @basekeys = refkeys, @joinkeys = forkeys, @filt_name = object_name(constid)
  13795.             from sysreferences where rkeyid = @base_objid and fkeyid = @join_objid
  13796.     
  13797.     /* Set up object names - we use them as correlation values */
  13798.     set @table_name = QUOTENAME(object_name(@base_objid))
  13799.     set @join_table = QUOTENAME(object_name(@join_objid))
  13800.     select @join_article = name from sysmergearticles where objid = @join_objid and pubid=@pubid
  13801.  
  13802.     -- set @qual_jointable = @join_owner + '.' + @join_table
  13803.  
  13804.     /* Loop over keys, building up our join filter clause */
  13805.     set @keyindex = 1
  13806.     set @first_piece = 0
  13807.     while @keyindex <= @keycnt
  13808.         begin
  13809.         /* Get the column names */
  13810.         
  13811.         /* also pass in vertical partitioning binary to excluded columns that are not in the current partition */
  13812.         exec dbo.sp_MSindexcolfrombin @base_objid, @keyindex, @basekeys, @basecol output, @base_columns
  13813.         if @@ERROR<>0 return (1)
  13814.         exec dbo.sp_MSindexcolfrombin @join_objid, @keyindex, @joinkeys, @joincol output, @join_columns
  13815.         if @@ERROR<>0 return (1)
  13816.  
  13817.         if @basecol is not NULL and @joincol is not NULL
  13818.         begin
  13819.             /* Make the piece of predicate pertaining to this key column */
  13820.             set @filtpiece = @table_name + '.' + @basecol + ' = ' + @join_table + '.' + @joincol
  13821.             
  13822.             /* If first time through, initialize clause, else add to it */
  13823.             if @first_piece=0
  13824.             begin
  13825.                 set @first_piece=1
  13826.                 set @filtclause = @filtpiece
  13827.             end
  13828.             else
  13829.                 set @filtclause = @filtclause + ' and ' + @filtpiece
  13830.         end
  13831.         /* move on to the next key */
  13832.         set @keyindex = @keyindex + 1
  13833.         end
  13834.  
  13835.     /* no filter generated due to vertical partitioning */
  13836.     if @first_piece>0
  13837.     begin
  13838.         /* Add the join filter */
  13839.         exec @retcode = dbo.sp_addmergefilter @publication, @article, @filt_name, @join_article, @filtclause, @join_unique
  13840.         if @@ERROR<>0 or @retcode<>0 return (1)
  13841.     end
  13842.  
  13843.     return (0)
  13844.     GO
  13845.  
  13846. exec dbo.sp_MS_marksystemobject sp_MSmakejoinfilter
  13847. go
  13848.  
  13849. raiserror('Creating procedure sp_MSmakeexpandproc', 0,1)
  13850. GO
  13851.  
  13852. create procedure sp_MSmakeexpandproc
  13853.     @pubname        sysname,
  13854.     @filterid       int,
  13855.     @procname       sysname
  13856.     AS
  13857.     /* Declare additional variables */
  13858.     declare @pubid  uniqueidentifier
  13859.     declare @base_nick int
  13860.     declare @join_nick int
  13861.     declare @base_nickstr nvarchar(10)
  13862.     declare @join_nickstr nvarchar(10)
  13863.     declare @filterid_str nvarchar(10)
  13864.     declare @base_objid int
  13865.     declare @join_objid int
  13866.     declare @base_table nvarchar(270)
  13867.     declare    @before_viewname    nvarchar(270)
  13868.     declare @join_table nvarchar(270)
  13869.     declare @base_owner nvarchar(270)
  13870.     declare @join_owner nvarchar(270)
  13871.     declare @join_clause nvarchar(4000)
  13872.     declare @retcode    int
  13873.     declare @must_check int
  13874.     declare @view_type  int
  13875.     declare @guidcolname    nvarchar(270)
  13876.     declare @joinguidname     nvarchar(270)
  13877.     declare @view_objid int
  13878.     declare @view_name  nvarchar(270)
  13879.     declare @cmd_piece  nvarchar(4000)
  13880.  
  13881.     select @pubid = pubid from sysmergepublications where name = @pubname and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  13882.  
  13883.     -- this procedure is to be called by xp_execresultset, so
  13884.     -- we create a temp table, put command pieces into it, and select them out
  13885.     
  13886.     -- create temp table to select the command text out of
  13887.     create table #tempcmd (step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  13888.  
  13889.     /* Figure out base table, join table for this join filter */
  13890.     select @base_nick = art_nickname, @join_nick = join_nickname,
  13891.         @join_clause = join_filterclause
  13892.         from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid
  13893.     select @base_objid = objid, @view_type = view_type, @view_objid = sync_objid from sysmergearticles where pubid = @pubid and nickname = @base_nick
  13894.     select @join_objid = objid, @before_viewname = object_name(before_view_objid)  from sysmergearticles where pubid = @pubid and nickname = @join_nick
  13895.     select @base_table = QUOTENAME(name), @base_owner = QUOTENAME(user_name(uid)) from sysobjects where id = @base_objid
  13896.     select @join_table = QUOTENAME(name), @join_owner = QUOTENAME(user_name(uid)) from sysobjects where id = @join_objid
  13897.     select @guidcolname = name from syscolumns where id = @base_objid and 
  13898.             columnproperty (id, name, 'isrowguidcol')=1
  13899.     select @joinguidname = name from syscolumns where id = @join_objid and 
  13900.             columnproperty (id, name, 'isrowguidcol')=1
  13901.     select @view_name = object_name(@view_objid)
  13902.     -- Quote the viewname.  It is made from pub name which may have odd characters.
  13903.     set @view_name = QUOTENAME(@view_name)
  13904.     set @base_nickstr = convert(nchar(10), @base_nick)
  13905.     set @join_nickstr = convert(nchar(10), @join_nick)
  13906.     set @filterid_str = convert(nchar(10), @filterid)
  13907.     
  13908.     set @cmd_piece = 'create procedure ' + @procname + ' 
  13909.         @belong int 
  13910.         AS 
  13911.             '
  13912.     insert into #tempcmd(cmdtext) values (@cmd_piece)
  13913.     set @cmd_piece = 'if @belong = 1
  13914.             begin
  13915.             /* Do a bulk insert to expand #belong */
  13916.             update #belong set flag = ' + @filterid_str + ' where flag < ' + @filterid_str + ' 
  13917.             insert into #belong (tablenick, rowguid, flag, skipexpand) select distinct ' + @base_nickstr +
  13918.             ', ' + @base_table + '.rowguidcol, 0, 0 from ' + @base_owner + '.' + @base_table + ', ' +
  13919.             @join_owner + '.' + @join_table + ', #belong b where (' + @join_clause + ') and ' + 
  13920.             @join_table + '.rowguidcol = b.rowguid and b.tablenick = ' + @join_nickstr + ' and skipexpand = 0 '
  13921.     insert into #tempcmd(cmdtext) values (@cmd_piece)
  13922.     set @cmd_piece = '  
  13923.         if @@ERROR <>0 return (1)
  13924.         /* Delete duplicates */
  13925.         delete from #belong where skipexpand = 1 and rowguid in
  13926.             (select rowguid from #belong where flag = 0)
  13927.         delete from #belong where flag = 0 and rowguid in
  13928.             (select rowguid from #belong where flag <> 0)
  13929.         end '
  13930.         insert into #tempcmd(cmdtext) values (@cmd_piece)
  13931.         
  13932.     /* Will we have to check rows that we add to #notbelong? */
  13933.     if exists (select * from sysmergearticles where pubid = @pubid and nickname = @join_nick and
  13934.         len(subset_filterclause) > 0)
  13935.         set @must_check = 1
  13936.     else if exists (select * from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid and
  13937.         join_unique_key <> 1)
  13938.         set @must_check = 1
  13939.     else if not exists (select * from sysmergesubsetfilters where pubid = @pubid and  art_nickname = @base_nick
  13940.             and join_filterid <> @filterid)
  13941.         set @must_check = 0
  13942.     
  13943.     set @cmd_piece = '
  13944.         else 
  13945.         begin
  13946.         update #notbelong set flag = ' + @filterid_str + ' where flag < ' + @filterid_str + ' 
  13947.         /* Do a bulk insert to expand #notbelong */
  13948.         insert into #notbelong (tablenick, rowguid, flag) select distinct ' + @base_nickstr +
  13949.             ', ' + @base_table + '.rowguidcol, -1 from ' + @base_owner + '.' + @base_table + ', ' +
  13950.             @join_owner + '.' + @join_table + ', #notbelong nb where (' + @join_clause + ') and ' + 
  13951.             @join_table + '.rowguidcol = nb.rowguid and nb.tablenick = ' + @join_nickstr + ' 
  13952.             /* Remove duplicates */
  13953.             delete from #notbelong where flag = -1 and rowguid in
  13954.                 (select rowguid from #notbelong where flag <> -1)
  13955.             '
  13956.     if @before_viewname  is not null
  13957.     set @cmd_piece = @cmd_piece + '
  13958.         insert into #notbelong (tablenick, rowguid, flag) select distinct ' + @base_nickstr +
  13959.             ', ' + @base_table + '.rowguidcol, -1 from ' + @base_owner + '.' + @base_table + ', ' +
  13960.             @before_viewname + ' ' + @join_table + ', #notbelong nb where (' + @join_clause + ') and ' + 
  13961.             @join_table + '.' + @joinguidname + ' = nb.rowguid and nb.tablenick = ' + @join_nickstr + ' 
  13962.             /* Remove duplicates */
  13963.             delete from #notbelong where flag = -1 and rowguid in
  13964.                 (select rowguid from #notbelong where flag <> -1)
  13965.             '
  13966.  
  13967.         
  13968.     if @must_check = 0
  13969.         begin
  13970.         insert into #tempcmd(cmdtext) values (@cmd_piece)
  13971.         set @cmd_piece = ' update #notbelong set flag = 0 where flag = -1 
  13972.             end '
  13973.         insert into #tempcmd(cmdtext) values (@cmd_piece)
  13974.         end
  13975.     else if @view_type = 1
  13976.         begin
  13977.         insert into #tempcmd(cmdtext) values (@cmd_piece)
  13978.         set @cmd_piece =  '     -- We can do our check with a bulk delete, bulk update
  13979.             delete from #notbelong where flag = -1 and rowguid in
  13980.                 (select ' + @guidcolname + ' from ' + @view_name + ')
  13981.             update #notbelong set flag = 0 where flag = -1
  13982.             end '
  13983.         insert into #tempcmd(cmdtext) values (@cmd_piece)
  13984.         end
  13985.     -- else we don't bother expanding #notbelong for this filter since there are cyclic
  13986.     -- join filters and this is not a unique key join.  The cursored calls to sp_belongs
  13987.     -- are unacceptably slow, and there would still be cases where orphaned rows could occur.
  13988.  
  13989. -- Now we select out the command text pieces in proper order so that our caller,
  13990. -- xp_execresultset will execute the command that creates the stored procedure.
  13991.  
  13992. select cmdtext from #tempcmd order by step
  13993.  
  13994. GO
  13995.  
  13996. exec dbo.sp_MS_marksystemobject sp_MSmakeexpandproc
  13997. go
  13998.  
  13999.  
  14000. raiserror('Creating procedure sp_MSdrop_expired_mergesubscription', 0,1)
  14001. GO
  14002.  
  14003. create procedure sp_MSdrop_expired_mergesubscription
  14004. AS
  14005. /*
  14006. ** This stored procedure is to periodically check the status of all the subscriptions 
  14007. ** of every merge publication. If any of them is out-of-date, i.e., has lost contact
  14008. ** with publisher for a certain length of time, we can declare the death of that replica
  14009. ** and cleanup their traces at the publisher side
  14010. */
  14011. declare @subscription_type  int
  14012. declare @sub_type           nvarchar(5)
  14013. declare @publication        sysname
  14014. declare @pubid              uniqueidentifier
  14015. declare @subid              uniqueidentifier
  14016. declare @status             tinyint
  14017. declare @publisher_id       int
  14018. declare @subscriber         sysname
  14019. declare @subscriber_id      int
  14020. declare @subscriber_db      sysname
  14021. declare @publisher_db       sysname
  14022. declare @retention          int  -- in days         
  14023. declare @retcode            smallint
  14024. declare @recgen             int
  14025. declare @sentgen            int
  14026. declare @max_distretention  int
  14027. declare @recent_merge       datetime
  14028. declare @minus_retention2   datetime
  14029. declare @minus_retention    datetime
  14030. declare @send_ts            datetime
  14031. declare @receive_ts         datetime
  14032.  
  14033. /*
  14034. ** Security Check
  14035. */
  14036.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  14037.     IF @@ERROR <> 0 or @retcode <> 0
  14038.         return (1)
  14039.  
  14040. /* we do not check return code here because we can tolerate any failure here */
  14041. exec @retcode = dbo.sp_MScleanup_conflict_table
  14042. if @@ERROR<>0 or @retcode<>0
  14043.     return (1)
  14044.  
  14045. declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s 
  14046.         where s.subid=p.pubid and s.pubid=p.pubid and p.snapshot_ready=1 for read only
  14047.     open PC
  14048.     fetch PC into @publication, @pubid, @retention 
  14049.     
  14050.     WHILE (@@fetch_status <> -1)
  14051.         BEGIN
  14052.             /* Compute the retention period cutoff dates per publication */
  14053.             select @minus_retention2 = dateadd(day, -@retention * 2, getdate())
  14054.             select @minus_retention = dateadd(day, -@retention, getdate())
  14055.             if @retention is not NULL and @retention > 0
  14056.             begin
  14057.                 -- this is to reomve any user script (file and directory) when following two points fulfills
  14058.                 -- 1. a snapshot has been run to pick it up
  14059.                 -- 2. the snapshot is too old that no new subscription need this file
  14060.                 exec @retcode = sp_MSremove_userscript @pubid
  14061.                 if @@ERROR<>0 or @retcode<>0
  14062.                 begin
  14063.                     close PC
  14064.                     deallocate PC
  14065.                     return (1)
  14066.                 end
  14067.                     declare SC CURSOR LOCAL FAST_FORWARD for select srvid, db_name, subid, status, subscription_type from sysmergesubscriptions where 
  14068.                     pubid = @pubid and pubid<>subid for read only
  14069.                    open SC
  14070.                 fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
  14071.                 WHILE (@@fetch_status <> -1)
  14072.                     BEGIN
  14073.                         select @subscriber=srvname from master..sysservers where srvid=@subscriber_id
  14074.                         if @subscription_type = 0 select @sub_type = 'push' else select @sub_type = 'pull'
  14075.                         select @receive_ts = coldate from MSmerge_genhistory 
  14076.                             where guidsrc = (select recguid from MSmerge_replinfo where repid = @subid)
  14077.                         select @sentgen=sentgen from MSmerge_replinfo where repid=@subid
  14078.                         select @send_ts = coldate from MSmerge_genhistory where generation=@sentgen
  14079.                         if @receive_ts>@send_ts select @recent_merge = @receive_ts
  14080.                             else select @recent_merge = @send_ts
  14081.                             
  14082.                         if @status <> 2 and @recent_merge<@minus_retention
  14083.                         begin
  14084.                             exec @retcode = dbo.sp_dropmergesubscription  
  14085.                                     @publication = @publication,
  14086.                                     @subscriber = @subscriber,
  14087.                                     @subscriber_db = @subscriber_db,
  14088.                                     @subscription_type = @sub_type  
  14089.                                if @retcode <>0 or @@ERROR<>0
  14090.                                 goto FAILURE
  14091.                             raiserror(14157, 10, -1, @subscriber, @publication) 
  14092.                         end
  14093.                         if @recent_merge<@minus_retention2 
  14094.                         begin
  14095.                             delete from sysmergesubscriptions where subid = @subid --delete the row in sysmergesubscription
  14096.                                if @@ERROR<>0
  14097.                                 goto FAILURE
  14098.                             delete from MSmerge_replinfo where repid = @subid
  14099.                             if @@ERROR<>0
  14100.                                 goto FAILURE
  14101.                         end     
  14102.                         fetch SC into @subscriber_id, @subscriber_db, @subid, @status, @subscription_type
  14103.                     END
  14104.                 CLOSE SC
  14105.                 DEALLOCATE SC
  14106.             end
  14107.             fetch PC into @publication, @pubid, @retention
  14108.         END
  14109.     CLOSE PC
  14110.     DEALLOCATE PC
  14111.     return (0)
  14112.     
  14113. FAILURE:
  14114.     close SC
  14115.     deallocate SC
  14116.     close PC
  14117.     deallocate PC
  14118.     return (1)
  14119.  
  14120. GO
  14121. exec dbo.sp_MS_marksystemobject sp_MSdrop_expired_mergesubscription
  14122. go
  14123.  
  14124. raiserror('Creating procedure sp_MScleanup_metadata', 0,1)
  14125. GO
  14126.  
  14127. create procedure sp_MScleanup_metadata
  14128. @pubid            uniqueidentifier
  14129. AS
  14130. declare @retcode                 int
  14131. declare @truncate_flag          int 
  14132. declare @pubid2                    uniqueidentifier
  14133. declare @artid                  uniqueidentifier
  14134. declare @schematype             int
  14135. declare @schemaversion          int
  14136. declare @schemaguid             uniqueidentifier
  14137. declare @schematext             nvarchar(2000)
  14138. declare @rcount                    int
  14139.  
  14140. set nocount on
  14141. /*
  14142. ** Security Check
  14143. */
  14144. EXEC @retcode = dbo.sp_MSreplcheck_publish
  14145. IF @@ERROR <> 0 or @retcode <> 0
  14146.     return (1)
  14147.     
  14148. if sessionproperty('replication_agent') <> 0
  14149.     begin
  14150.     -- called from Merge Agent.  If we are republishing, must add this command for
  14151.     -- any publications which are republishing data from the original publication.
  14152.  
  14153.     declare #per_publication CURSOR LOCAL FAST_FORWARD for select pubid
  14154.         from sysmergepublications p where LOWER(publisher)=LOWER(@@SERVERNAME) and 
  14155.                 publisher_db=db_name() and 
  14156.             exists (select * from sysmergearticles a1, sysmergearticles a2 where
  14157.                     a1.pubid = p.pubid and a2.pubid = @pubid and a1.objid = a2.objid)
  14158.     open #per_publication        
  14159.     fetch #per_publication into @pubid2
  14160.     while @@fetch_status<>-1
  14161.         begin
  14162.            select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  14163.         if (@schemaversion is NULL)
  14164.                set @schemaversion = 1
  14165.         set @schemaguid = newid()
  14166.            set @artid = newid()
  14167.            set @schematype = 16 /* metadata cleanup */
  14168.            select @schematext = 'exec dbo.sp_MScleanup_metadata '+ '''' + convert(nchar(36),@pubid2) + '''' 
  14169.         exec @retcode=sp_MSinsertschemachange @pubid2, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  14170.         if @@ERROR<>0 or @retcode<>0 
  14171.             begin
  14172.             close #per_publication
  14173.             deallocate #per_publication
  14174.             return (1)
  14175.           
  14176.             end
  14177.     
  14178.         fetch next from #per_publication into @pubid2
  14179.         end
  14180.     close #per_publication
  14181.     deallocate #per_publication
  14182.       end
  14183. else
  14184.       begin
  14185.       -- should be nested call from sp_mergecleanupmetadata and we should be the
  14186.       -- publisher of this publication
  14187.     if @pubid is not null and not exists (select * from sysmergepublications where
  14188.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and pubid = @pubid)
  14189.         begin
  14190.         return (1)
  14191.         end
  14192.       end
  14193.  
  14194. -- Figure out whether there are any publications which prevent us from truncating the tables
  14195. if @pubid is null
  14196.     begin
  14197.     if exists (select * from sysmergepublications where
  14198.         LOWER(publisher)<> LOWER(@@SERVERNAME) or publisher_db<>db_name())
  14199.         set @truncate_flag = 0
  14200.     else
  14201.         set @truncate_flag = 1
  14202.     end
  14203. else
  14204.     begin
  14205.     if exists (select * from sysmergepublications p where p.pubid <> @pubid and
  14206.         (LOWER(publisher)<> LOWER(@@SERVERNAME) or publisher_db<>db_name() or
  14207.         not exists (select * from sysmergearticles a1, sysmergearticles a2 where
  14208.             a1.pubid = p.pubid and a2.pubid = @pubid and a1.objid = a2.objid)))
  14209.         set @truncate_flag = 0
  14210.     else
  14211.         set @truncate_flag = 1    
  14212.     end
  14213.  
  14214.  
  14215. if @pubid is not null
  14216.     begin
  14217.         /* If there are any inprocess generations inform user that queisce did not succeed - reinit required  */
  14218.         if exists (select top 1 guidsrc from dbo.MSmerge_genhistory h
  14219.             where    guidlocal='00000000-0000-0000-0000-000000000000'  -- incomplete gen
  14220.                 and generation not in (select gen_cur from sysmergearticles)  -- not a local incomplete gen
  14221.                 and coldate in (select login_time from master..sysprocesses)  -- not a gen that currently receives replica updates from another db
  14222.                 and h.art_nick in (select nickname from sysmergearticles where pubid = @pubid)) -- generations relevant to current publication 
  14223.             begin
  14224.                 declare @dbname sysname
  14225.                 set @dbname = db_name()
  14226.                 RAISERROR(21504, 16, -1, @@servername, @dbname)
  14227.                 return (1)
  14228.             end
  14229.     end
  14230. if @truncate_flag = 1
  14231.     begin
  14232.     truncate table MSmerge_contents
  14233.     truncate table MSmerge_tombstone
  14234.     truncate table MSmerge_genhistory
  14235.     update sysmergearticles set gen_cur = NULL
  14236.     update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  14237.     end
  14238. else
  14239.     begin
  14240.     -- set up temp table of article nicknames that we delete for
  14241.     create table #artnicks (nickname int)
  14242.     if @pubid is null
  14243.         begin
  14244.         -- insert pubids for all local publications
  14245.         insert into #artnicks select distinct nickname from sysmergearticles where
  14246.             pubid in (select pubid from sysmergepublications where
  14247.                 LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name())
  14248.         end
  14249.     else
  14250.         begin
  14251.         insert into #artnicks select distinct nickname from sysmergearticles where
  14252.             pubid = @pubid
  14253.         end
  14254.     
  14255.         
  14256.     -- do deletions in batches of 5000 to avoid excessive log growth
  14257.     
  14258.     set rowcount 5000
  14259.     set @rcount = 1
  14260.     while @rcount > 0
  14261.         begin
  14262.         set @rcount = 0
  14263.  
  14264.         -- update our cumulative count of rows deleted in this pass with each table
  14265.         delete MSmerge_contents WITH (PAGLOCK) from MSmerge_contents where tablenick in (select nickname from #artnicks)
  14266.         set @rcount = @@rowcount + @rcount
  14267.         delete MSmerge_tombstone WITH (PAGLOCK) from MSmerge_tombstone where tablenick in (select nickname from #artnicks)
  14268.         set @rcount = @@rowcount + @rcount
  14269.         delete MSmerge_genhistory WITH (PAGLOCK) from MSmerge_genhistory where art_nick in (select nickname from #artnicks)
  14270.         set @rcount = @@rowcount + @rcount
  14271.         end
  14272.     
  14273.     update sysmergearticles set gen_cur = NULL where nickname in (select nickname from #artnicks)
  14274.  
  14275.     if @pubid is not null
  14276.         update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  14277.             where repid in ( select subid from sysmergesubscriptions where pubid = @pubid)
  14278.     else
  14279.         update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  14280.             where repid in ( select subid from sysmergesubscriptions s, sysmergepublications p
  14281.                 where s.pubid = p.pubid and LOWER(p.publisher)=LOWER(@@SERVERNAME) and p.publisher_db=db_name())
  14282.     
  14283.     drop table #artnicks
  14284.     dbcc dbreindex ( MSmerge_contents )
  14285.     end
  14286.  
  14287. execute @retcode = dbo.sp_MSmakegeneration 
  14288. if @@ERROR <> 0 or @retcode <> 0
  14289.     return (1)
  14290. return 0
  14291.  
  14292. GO
  14293. exec dbo.sp_MS_marksystemobject sp_MScleanup_metadata
  14294. go
  14295. grant execute on dbo.sp_MScleanup_metadata to public
  14296. go
  14297.  
  14298.  
  14299. raiserror('Creating procedure sp_helpmergecleanupwait', 0,1)
  14300. GO
  14301. create procedure sp_helpmergecleanupwait
  14302. AS
  14303.     -- Tell user if we don't think we are waiting!
  14304.     if not exists (select * from sysmergesubscriptions where status = 7)
  14305.         raiserror(21507, 0,1)
  14306.  
  14307.     if exists (select * from sysmergepublications p, sysmergesubscriptions s
  14308.             where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and
  14309.                 p.pubid = s.pubid and s.status = 7 and s.subid <> s.pubid)
  14310.         begin
  14311.         raiserror(21509, 0,1)
  14312.         select publication, srvid, db_name from sysmergesubscriptions where status = 7
  14313.         end
  14314.     else if exists (select * from MSmerge_genhistory, master..sysprocesses where guidlocal = '00000000-0000-0000-0000-000000000000' and
  14315.             coldate = login_time)
  14316.         begin
  14317.         raiserror(21508, 0,1)
  14318.         select hostname, program_name from master..sysprocesses where login_time in
  14319.             (select coldate from MSmerge_genhistory where guidlocal = '00000000-0000-0000-0000-000000000000')
  14320.         end
  14321.     else
  14322.         exec sp_MSquiescecheck
  14323.     
  14324. GO
  14325.  
  14326. grant execute on sp_helpmergecleanupwait to public
  14327. GO
  14328.  
  14329.  
  14330. exec dbo.sp_MS_marksystemobject sp_helpmergecleanupwait
  14331. go
  14332. raiserror('Creating procedure sp_MSquiescecheck', 0,1)
  14333. GO
  14334.  
  14335. create procedure sp_MSquiescecheck
  14336. AS
  14337.     declare @mysrvid        int
  14338.     declare @pubid            uniqueidentifier
  14339.     declare @retcode        int
  14340.  
  14341.     set nocount on
  14342.  
  14343.     -- If we are not waiting to quiesce, do nothing more
  14344.     if not exists (select * from sysmergesubscriptions where status = 7)
  14345.         return 0
  14346.  
  14347.     -- If we publish to any republishers who are still waiting to
  14348.     -- quiesce (status = 7) then just return for now.
  14349.     if exists (select * from sysmergepublications p, sysmergesubscriptions s
  14350.             where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and
  14351.                 p.pubid = s.pubid and s.status = 7 and s.subid <> s.pubid)
  14352.         return 0
  14353.  
  14354.     -- Set publication status to inactive for all publications I have that are participating
  14355.     -- in the metadata cleanup.
  14356.     update sysmergepublications set status = 0 where LOWER(publisher)=LOWER(@@SERVERNAME) and
  14357.         publisher_db=db_name() and pubid in
  14358.             (select a1.pubid from sysmergearticles a1, sysmergearticles a2, sysmergesubscriptions s
  14359.                 where a1.objid = a2.objid and a2.pubid = s.pubid and s.status = 7)
  14360.                 
  14361.     -- If there are any open generations with more than 0 rows, we must still wait
  14362.     if exists (select * from MSmerge_genhistory gh where guidlocal = '00000000-0000-0000-0000-000000000000' and
  14363.                 generation not in (select gen_cur from sysmergearticles) 
  14364.                     and coldate in (select login_time from master..sysprocesses)) 
  14365.         return 0
  14366.  
  14367.     
  14368.  
  14369.     -- Am I the top-level publisher or just a republisher?
  14370.     set @mysrvid = 0
  14371.     select @mysrvid = srvid from master..sysservers where srvname = @@SERVERNAME
  14372.     if exists (select * from sysmergesubscriptions s where srvid = @mysrvid and
  14373.         db_name = db_name() and status = 7 and subid <> pubid)
  14374.         begin
  14375.         -- I am not the top level publisher.  Just set my status & let it propagate up.
  14376.         update sysmergesubscriptions set status = 8 where
  14377.             srvid = @mysrvid and db_name = db_name() and status = 7
  14378.         return 0
  14379.         end
  14380.     else
  14381.         begin
  14382.         -- I am the top level publisher!  Start getting rid of that old metadata!
  14383.         select @pubid = pubid from sysmergesubscriptions where srvid = @mysrvid and
  14384.             db_name = db_name() and status = 7
  14385.         exec @retcode = dbo.sp_MScompletecleanup @pubid
  14386.         return @retcode
  14387.         end
  14388.             
  14389. GO
  14390. exec dbo.sp_MS_marksystemobject sp_MSquiescecheck
  14391. go
  14392. grant execute on dbo.sp_MSquiescecheck to public
  14393. go
  14394.  
  14395. raiserror('Creating procedure sp_mergepreparecleanup', 0,1)
  14396. GO
  14397.  
  14398. create procedure sp_mergepreparecleanup
  14399.     @publication    sysname
  14400. AS
  14401. declare @pubid            uniqueidentifier
  14402. declare @retcode        int
  14403.  
  14404. declare @schematype             int
  14405. declare @schematext             nvarchar(2000)
  14406. /*
  14407. ** Security Check
  14408. */
  14409. EXEC @retcode = dbo.sp_MSreplcheck_publish
  14410. IF @@ERROR <> 0 or @retcode <> 0
  14411.     return (1)
  14412.  
  14413. set nocount on
  14414.  
  14415. /* Validate the publication  */
  14416. select @pubid = pubid from sysmergepublications 
  14417.         where name = @publication and 
  14418.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()
  14419.         
  14420. if @pubid is NULL
  14421.         begin
  14422.            raiserror (20026, 11, -1, @publication)
  14423.         return (1)
  14424.         end
  14425. if exists (select * from sysmergearticles a1, sysmergearticles a2
  14426.      where a1.pubid = @pubid and a2.objid = a1.objid and
  14427.         a2.pubid not in (select pubid from sysmergepublications where
  14428.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()))
  14429.         begin
  14430.         raiserror(21272, 16, -1, @publication)
  14431.         return (1)
  14432.         end
  14433.  
  14434. exec @retcode=sp_MSBumpupCompLevel @pubid, 40 
  14435. if @@ERROR<>0 or @retcode<>0        
  14436.     return (1)
  14437.         
  14438. -- stop local updates by creating the quiesce triggers
  14439. exec @retcode = sp_MSquiescetriggerson
  14440.  
  14441. -- use publisher row in sysmergesubscriptions to store datetime we started quiesce sequence
  14442. update sysmergesubscriptions set last_sync_date = getdate() where pubid = @pubid and subid = @pubid
  14443.  
  14444. -- insert a schema change that will cause subscribers and republishers to prepare for cleanup
  14445. set @schematype = 17 /* metadata cleanup */
  14446. set @schematext = 'exec dbo.sp_MSpreparecleanup '
  14447. exec sp_MSpropagateschematorepubs @pubid, @schematext, @schematype
  14448.        
  14449. GO
  14450.  
  14451. exec dbo.sp_MS_marksystemobject sp_mergepreparecleanup
  14452. go
  14453. grant execute on dbo.sp_mergepreparecleanup to public
  14454. go
  14455.  
  14456. raiserror('Creating procedure sp_MSpreparecleanup', 0,1)
  14457. GO
  14458.  
  14459. create procedure sp_MSpreparecleanup
  14460.     @pubid            uniqueidentifier
  14461. AS
  14462. declare @retcode         int
  14463. declare @schematype             int
  14464. declare @schematext             nvarchar(2000)
  14465.  
  14466. -- This should only be invoked by the merge agent as it processes schema changes
  14467. if sessionproperty('replication_agent') = 0
  14468.     return (1)
  14469.  
  14470. set nocount on
  14471.  
  14472. exec @retcode=sp_MSBumpupCompLevel @pubid, 40 
  14473. if @@ERROR<>0 or @retcode<>0        
  14474.     return (1)
  14475.  
  14476. -- stop local updates by creating the quiesce triggers
  14477. exec @retcode = sp_MSquiescetriggerson
  14478.  
  14479. -- If we are a republisher, propagate the schema change on to our subscribers
  14480. set @schematype = 17 /* prepare cleanup */
  14481. select @schematext = 'exec dbo.sp_MSpreparecleanup '
  14482. exec sp_MSpropagateschematorepubs @pubid, @schematext, @schematype
  14483. return (0)
  14484.  
  14485. GO
  14486.  
  14487. exec dbo.sp_MS_marksystemobject sp_MSpreparecleanup
  14488. go
  14489. grant execute on dbo.sp_MSpreparecleanup to public
  14490. go
  14491.  
  14492. raiserror('Creating procedure sp_MSquiescetriggerson', 0,1)
  14493. GO
  14494.  
  14495. create procedure sp_MSquiescetriggerson
  14496. AS
  14497. declare @cmd nvarchar(4000)
  14498.  
  14499. if not exists (select * from sysobjects where xtype = N'TR' and name = 'MS_mergequiescetrigger')
  14500.     begin
  14501.     set @cmd = 'create trigger MS_mergequiescetrigger on MSmerge_contents for UPDATE, INSERT, DELETE 
  14502.     NOT FOR REPLICATION AS
  14503.     if sessionproperty(''replication_agent'') = 0
  14504.         begin
  14505.         -- Raise an appropriate error
  14506.         RAISERROR(21510, 11, -1)
  14507.         rollback tran
  14508.         end'
  14509.     execute (@cmd)
  14510.     end
  14511.  
  14512. if not exists (select * from sysobjects where xtype = N'TR' and name = 'MS_mergequiescetrigger2')
  14513. begin
  14514.     set @cmd = 'create trigger MS_mergequiescetrigger2 on MSmerge_tombstone for UPDATE, INSERT, DELETE 
  14515.     NOT FOR REPLICATION AS
  14516.     if sessionproperty(''replication_agent'') = 0
  14517.         begin
  14518.         -- Raise an appropriate error
  14519.         RAISERROR(21510, 11, -1)
  14520.         rollback tran
  14521.         end'
  14522.     execute (@cmd)    
  14523.     end
  14524. GO
  14525. exec dbo.sp_MS_marksystemobject sp_MSquiescetriggerson
  14526. go
  14527. grant execute on dbo.sp_MSquiescetriggerson to public
  14528. go
  14529.  
  14530. raiserror('Creating procedure sp_MSquiescetriggersoff', 0,1)
  14531. GO
  14532.  
  14533. create procedure sp_MSquiescetriggersoff
  14534. AS
  14535.     if exists (select * from sysobjects where xtype = N'TR' and name = 'MS_mergequiescetrigger')
  14536.         drop trigger MS_mergequiescetrigger
  14537.     if exists (select * from sysobjects where xtype = N'TR' and name = 'MS_mergequiescetrigger2')
  14538.         drop trigger MS_mergequiescetrigger2
  14539.  
  14540. GO
  14541. exec dbo.sp_MS_marksystemobject sp_MSquiescetriggersoff
  14542. go
  14543. raiserror('Creating procedure sp_MSquiesceforcleanup', 0,1)
  14544. GO
  14545. create procedure sp_MSquiesceforcleanup    
  14546.     @pubid     uniqueidentifier
  14547. AS
  14548.     declare @schematype     int
  14549.     declare @schematext        nvarchar(4000)
  14550.     declare @mysrvid                int
  14551.     declare @retcode int
  14552.  
  14553.     set nocount on
  14554.  
  14555.     set @mysrvid = 0
  14556.     select @mysrvid = srvid from master..sysservers where srvname = @@SERVERNAME
  14557.  
  14558.     -- @pubid is normally the publication I subscribe to, get the pubid's of what I republish
  14559.     create table #mypubids(pubid uniqueidentifier)
  14560.  
  14561.     insert into #mypubids (pubid) select distinct p.pubid from sysmergepublications p,
  14562.             sysmergearticles a1, sysmergearticles a2
  14563.         where a1.pubid = @pubid and a1.objid = a2.objid and p.pubid = a2.pubid and
  14564.              LOWER(p.publisher)=LOWER(@@SERVERNAME) and p.publisher_db=db_name()
  14565.  
  14566.     -- If I don't republish, then I am done and ready
  14567.     if @@ROWCOUNT = 0
  14568.         begin
  14569.         drop table #mypubids
  14570.         
  14571.         -- REPLICA_STATUS_ReadyForCleanup         = 0x0008
  14572.         update sysmergesubscriptions set status = 8 where pubid = @pubid and
  14573.             db_name = db_name() and srvid = @mysrvid
  14574.         
  14575.         return 0
  14576.         end
  14577.  
  14578.     -- set my status to QuiesceRequested
  14579.     -- REPLICA_STATUS_QuieseRequested    = 0x0007,
  14580.     update sysmergesubscriptions set status = 7 where pubid = @pubid and
  14581.             db_name = db_name() and srvid = @mysrvid
  14582.     update sysmergesubscriptions set status = 7 where pubid in (select pubid from #mypubids) and
  14583.         db_name = db_name() and srvid = @mysrvid
  14584.  
  14585.     -- update status for my republishing subscribers
  14586.     update sysmergesubscriptions set status = 7 where pubid in (select pubid from #mypubids)
  14587.         and subid in (select s1.subid from sysmergesubscriptions s1, sysmergesubscriptions s2
  14588.                 where s1.pubid in (select pubid from #mypubids) and s1.srvid = s2.srvid and
  14589.                 s1.db_name = s2.db_name and s2.subid = s2.pubid and s2.status = 1)
  14590.  
  14591.     -- check if any of my subscribers republish
  14592.     if @@ROWCOUNT = 0
  14593.         begin
  14594.         -- If none of my subscribers are republishers, then I just
  14595.         -- set my publications' status to unavailable and set
  14596.         -- set my replica status as ReadyForCleanup
  14597.  
  14598.         update sysmergepublications set status = 0 where pubid in (select pubid from #mypubids)
  14599.         -- I may have ongoing merges call the quiescecheck routine to try and set my status
  14600.         exec @retcode = sp_MSquiescecheck                    
  14601.         end
  14602.     else
  14603.         begin
  14604.         -- propagate the schema change on to my subscribers
  14605.         set @schematype = 19  -- SCHEMA_TYPE_QUIESCE            = 19
  14606.         set @schematext = 'exec dbo.sp_MSquiesceforcleanup '
  14607.         exec sp_MSpropagateschematorepubs @pubid, @schematext, @schematype
  14608.         end
  14609.     drop table #mypubids
  14610. GO
  14611.  
  14612. grant execute on dbo.sp_MSquiesceforcleanup to public
  14613. go
  14614.  
  14615. exec dbo.sp_MS_marksystemobject sp_MSquiesceforcleanup
  14616. go
  14617.  
  14618. raiserror('Creating procedure sp_mergecompletecleanup', 0,1)
  14619. GO
  14620.  
  14621. create procedure sp_mergecompletecleanup
  14622.     @publication        sysname
  14623. AS
  14624. declare @pubid            uniqueidentifier
  14625. declare @retcode        int
  14626.  
  14627. set nocount on
  14628.  
  14629. /*
  14630. ** Security Check
  14631. */
  14632. EXEC @retcode = dbo.sp_MSreplcheck_publish
  14633. IF @@ERROR <> 0 or @retcode <> 0
  14634.     return (1)
  14635. /* make sure current database is enabled for merge replication */
  14636. exec @retcode=dbo.sp_MSCheckmergereplication
  14637. if @@ERROR<>0 or @retcode<>0
  14638.     return (1)
  14639.     
  14640.  
  14641. /* Validate the publication  */
  14642. select @pubid = pubid from sysmergepublications 
  14643.         where name = @publication and 
  14644.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()
  14645.         
  14646. if @pubid is NULL
  14647.         begin
  14648.                raiserror (20026, 11, -1, @publication)
  14649.             return (1)
  14650.         end
  14651. -- Make sure we are at the top-level publisher
  14652.  
  14653. if exists (select * from sysmergearticles a1, sysmergearticles a2
  14654.      where a1.pubid = @pubid and a2.objid = a1.objid and
  14655.         a2.pubid not in (select pubid from sysmergepublications where
  14656.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()))
  14657.         begin
  14658.         raiserror(21272, 16, -1, @publication)
  14659.         return (1)
  14660.         end
  14661.         
  14662. -- If user never id sp_mergepreparecleanup then inform them of their error.
  14663. if not exists(select * from sysmergeschemachange where schematype = 17)
  14664.     begin
  14665.     raiserror(21506, 0, 1)
  14666.     return (1)
  14667.     end
  14668.  
  14669. -- Use sp_MSquiesceforcleanup to propagate schema, etc.
  14670. exec @retcode = sp_MSquiesceforcleanup @pubid
  14671. if @@ERROR<>0 or @retcode<>0
  14672.     return (1)
  14673.  
  14674.     
  14675. GO
  14676. exec dbo.sp_MS_marksystemobject sp_mergecompletecleanup
  14677. go
  14678.  
  14679. grant execute on dbo.sp_mergecompletecleanup to public
  14680. go
  14681.  
  14682. raiserror('Creating procedure sp_MScompletecleanup', 0,1)
  14683. GO
  14684.  
  14685. create procedure sp_MScompletecleanup
  14686. @pubid            uniqueidentifier
  14687. AS
  14688. declare @retcode         int
  14689. declare @otherpubs  int 
  14690. declare @pubid2        uniqueidentifier
  14691. declare @artid                  uniqueidentifier
  14692. declare @schematype             int
  14693. declare @schemaversion          int
  14694. declare @schemaguid             uniqueidentifier
  14695. declare @schematext             nvarchar(2000)
  14696. declare @rcount                        int
  14697. declare @dtprepare                datetime
  14698. declare @cutoffgen                int
  14699. declare @mysrvid                int
  14700. declare @toplevel                int
  14701.  
  14702. set nocount on
  14703.  
  14704. if exists (select * from sysmergepublications where pubid = @pubid and
  14705.         LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name())
  14706.     set @toplevel = 1
  14707. else
  14708.     set @toplevel = 0
  14709.     
  14710. /*
  14711. ** Security Check
  14712. */
  14713. EXEC @retcode = dbo.sp_MSreplcheck_publish
  14714. IF @@ERROR <> 0 or @retcode <> 0
  14715.     return (1)
  14716.  
  14717. -- Figure out whether there are any other publications which make us copy additional rows
  14718. set @otherpubs = 0
  14719.  
  14720. if exists (select * from sysmergearticles a1 where a1.objid not in
  14721.                 (select objid from sysmergearticles where pubid = @pubid))
  14722.     set @otherpubs = 1
  14723.  
  14724. if @otherpubs = 1 or @toplevel = 1
  14725.     begin
  14726.     -- create some temp tables to preserve part of MSmerge_contents
  14727.     create table #contents (tablenick int NOT NULL,
  14728.                 rowguid            uniqueidentifier rowguidcol   NOT NULL,
  14729.                 generation        int                    NOT NULL,
  14730.                 partchangegen    int                    NULL,
  14731.                 joinchangegen    int                    NULL,
  14732.                 lineage            varbinary(249)        NOT NULL,
  14733.                 colv1            varbinary(2048)        NULL)
  14734.  
  14735.     create table #tombstone (rowguid            uniqueidentifier rowguidcol NOT NULL,
  14736.                 tablenick        int                NOT NULL,
  14737.                 type            tinyint            NOT NULL,
  14738.                 lineage            varbinary(249)    NOT NULL,
  14739.                 generation        int                NOT NULL,
  14740.                 reason            nvarchar(255)    NOT NULL)
  14741.  
  14742.     end
  14743.     
  14744.     -- propagate the schema change on to our subscribers
  14745.        set @schematype = 18 /* metadata cleanup */
  14746.     select @schematext = 'exec dbo.sp_MScompletecleanup '
  14747.     exec sp_MSpropagateschematorepubs @pubid, @schematext, @schematype
  14748.  
  14749. if @toplevel = 1
  14750.       begin                
  14751.      /* Get the timestamp when we did the prepareforcleanup */
  14752.     select @dtprepare = last_sync_date from sysmergesubscriptions where pubid = @pubid and
  14753.             subid = @pubid
  14754.     -- Copy some generations from contents and tombstone into temptables
  14755.     select @cutoffgen = min(generation) from MSmerge_genhistory where coldate > @dtprepare
  14756.     
  14757.     if @otherpubs = 1
  14758.         begin
  14759.         insert into #contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1)
  14760.                 select tablenick, rowguid, 0,
  14761.                         case when partchangegen < @cutoffgen then NULL else 0 end,
  14762.                         case when joinchangegen < @cutoffgen then NULL else 0 end,
  14763.                 lineage, colv1 from MSmerge_contents where generation >= @cutoffgen and tablenick
  14764.                     in (select nickname from sysmergearticles where pubid = @pubid)
  14765.         end
  14766.     else
  14767.         begin
  14768.         -- leaving out join to sysmergearticles should help performance
  14769.         insert into #contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1)
  14770.                 select tablenick, rowguid, 0,
  14771.                         case when partchangegen < @cutoffgen then NULL else 0 end,
  14772.                         case when joinchangegen < @cutoffgen then NULL else 0 end,
  14773.                 lineage, colv1 from MSmerge_contents where generation >= @cutoffgen 
  14774.         end
  14775.                 
  14776.     if @otherpubs = 1
  14777.         begin
  14778.         insert into #tombstone (rowguid, tablenick, type, lineage, generation, reason)
  14779.             select rowguid, tablenick, type, lineage, 0, reason
  14780.             from MSmerge_tombstone where generation >= @cutoffgen and tablenick
  14781.                 in (select nickname from sysmergearticles where pubid = @pubid)
  14782.         end
  14783.     else
  14784.         begin
  14785.         insert into #tombstone (rowguid, tablenick, type, lineage, generation, reason)
  14786.             select rowguid, tablenick, type, lineage, 0, reason
  14787.             from MSmerge_tombstone where generation >= @cutoffgen    
  14788.         end
  14789.      end
  14790.  
  14791. if @otherpubs = 1
  14792.     begin
  14793.     insert into #contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1)
  14794.         select * from MSmerge_contents where tablenick not in
  14795.             (select nickname from sysmergearticles where pubid = @pubid)
  14796.     insert into #tombstone (rowguid, tablenick, type, lineage, generation, reason)
  14797.         select * from MSmerge_tombstone where tablenick not in
  14798.             (select nickname from sysmergearticles where pubid = @pubid)
  14799.     end
  14800.     
  14801. truncate table MSmerge_contents
  14802. truncate table MSmerge_tombstone
  14803.  
  14804. if @otherpubs = 0
  14805.     begin
  14806.     truncate table MSmerge_genhistory
  14807.     update sysmergearticles set gen_cur = NULL
  14808.     update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  14809.     end
  14810. else
  14811.     begin
  14812.     -- set up temp table of article nicknames that we delete for
  14813.     create table #artnicks (nickname int)
  14814.     insert into #artnicks select distinct nickname from sysmergearticles where
  14815.             pubid = @pubid
  14816.             
  14817.     -- do deletions in batches of 5000 to avoid excessive log growth
  14818.     set rowcount 5000
  14819.     set @rcount = 1
  14820.     while @rcount > 0
  14821.         begin
  14822.         set @rcount = 0
  14823.         delete MSmerge_genhistory WITH (PAGLOCK) from MSmerge_genhistory where art_nick in (select nickname from #artnicks)
  14824.         set @rcount = @@rowcount
  14825.         end
  14826.     
  14827.     update sysmergearticles set gen_cur = NULL where nickname in (select nickname from #artnicks)
  14828.  
  14829.     update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL 
  14830.             where repid in ( select subid from sysmergesubscriptions where pubid = @pubid)
  14831.     
  14832.     drop table #artnicks
  14833.     end
  14834.  
  14835. -- Remove triggers now so we can reinsert the rows we saved from contents
  14836.     execute @retcode = sp_MSquiescetriggersoff
  14837.  
  14838. if @toplevel = 1 or @otherpubs = 1
  14839.     begin
  14840.     -- Put back the rows from #contents and #tombstone
  14841.     insert into MSmerge_contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1)
  14842.         select * from #contents
  14843.     insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason)
  14844.         select * from #tombstone
  14845.     end
  14846.  
  14847. -- Mark publications as active but snapshot expired
  14848. update sysmergepublications set status = 1, snapshot_ready = 3 where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and 
  14849.         pubid in (select a1.pubid from sysmergearticles a1, sysmergearticles a2 where
  14850.                     a2.pubid = @pubid and a1.objid = a2.objid)
  14851.  
  14852. -- Set our subscriber status back to 1
  14853. set @mysrvid = 0
  14854. select @mysrvid = srvid from master..sysservers where srvname = @@SERVERNAME
  14855. update sysmergesubscriptions set status = 1 where srvid = @mysrvid and db_name = db_name() and
  14856.     pubid in (select a1.pubid from sysmergearticles a1, sysmergearticles a2 where a1.objid = a2.objid 
  14857.                 and a2.pubid = @pubid)
  14858. -- update subscriptions rows that still say status of ReadyForCleanup
  14859. update sysmergesubscriptions set status = 1 where status = 8
  14860.                 
  14861. execute @retcode = dbo.sp_MSmakegeneration 
  14862. if @@ERROR <> 0 or @retcode <> 0
  14863.     return (1)
  14864. return 0
  14865.  
  14866. GO
  14867. exec dbo.sp_MS_marksystemobject sp_MScompletecleanup
  14868. go
  14869.  
  14870. raiserror('Creating procedure sp_MSpropagateschematorepubs', 0,1)
  14871. GO
  14872.  
  14873. create procedure sp_MSpropagateschematorepubs
  14874.     @pubid        uniqueidentifier,
  14875.     @schema_text    nvarchar(4000),
  14876.     @schema_type int
  14877. AS
  14878. declare @pubid2            uniqueidentifier
  14879. declare @artid            uniqueidentifier
  14880. declare @fulltext        nvarchar(4000)
  14881. declare @retcode        int
  14882. declare @schemaversion          int
  14883. declare @schemaguid             uniqueidentifier
  14884. declare @schematext             nvarchar(2000)
  14885.  
  14886. set nocount on
  14887.  
  14888.     -- Find republications and add the same schema change
  14889.     declare #per_publication CURSOR LOCAL FAST_FORWARD for select pubid
  14890.         from sysmergepublications p where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and 
  14891.             exists (select * from sysmergearticles a1, sysmergearticles a2 where
  14892.                     a1.pubid = p.pubid and a2.pubid = @pubid and a1.objid = a2.objid)
  14893.     open #per_publication        
  14894.     fetch #per_publication into @pubid2
  14895.     while @@fetch_status<>-1
  14896.         begin
  14897.            select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  14898.         if (@schemaversion is NULL)
  14899.                set @schemaversion = 1
  14900.         set @schemaguid = newid()
  14901.            set @artid = newid()
  14902.            select @fulltext = @schema_text + ' ''' + convert(nchar(36),@pubid2) + '''' 
  14903.         exec @retcode=sp_MSinsertschemachange @pubid2, @artid, @schemaversion, @schemaguid, @schema_type, @fulltext
  14904.         if @@ERROR<>0 or @retcode<>0 
  14905.             begin
  14906.             close #per_publication
  14907.             deallocate #per_publication
  14908.             return (1)
  14909.           
  14910.             end
  14911.         fetch next from #per_publication into @pubid2
  14912.         end
  14913.     close #per_publication
  14914.     deallocate #per_publication
  14915.     return (0)
  14916. GO
  14917. exec dbo.sp_MS_marksystemobject sp_MSpropagateschematorepubs
  14918. go
  14919.  
  14920.  
  14921. raiserror('Creating procedure sp_mergecleanupmetadata', 0,1)
  14922. GO
  14923.  
  14924. create procedure sp_mergecleanupmetadata
  14925.     @publication        sysname = '%',
  14926.     @reinitialize_subscriber    nvarchar(5) = 'true'
  14927. AS
  14928. declare @pubid                    uniqueidentifier
  14929. declare @retcode                int
  14930. declare @pubname                  sysname
  14931. declare @snapshot_ready         int
  14932. declare @make_generation         int
  14933. declare @artid                  uniqueidentifier
  14934. declare @schematype             int
  14935. declare @schemaversion          int
  14936. declare @schemaguid             uniqueidentifier
  14937. declare @schematext             nvarchar(2000)
  14938.  
  14939. set @make_generation = 0
  14940. /*
  14941. ** Security Check
  14942. */
  14943. EXEC @retcode = dbo.sp_MSreplcheck_publish
  14944. IF @@ERROR <> 0 or @retcode <> 0
  14945.     return (1)
  14946. /* make sure current database is enabled for merge replication */
  14947. exec @retcode=dbo.sp_MSCheckmergereplication
  14948. if @@ERROR<>0 or @retcode<>0
  14949.     return (1)
  14950.     
  14951.  
  14952. /* Validate the publication name if one is provided */
  14953. if @publication <> '%'
  14954.     begin
  14955.         select @pubid = pubid from sysmergepublications 
  14956.             where name = @publication
  14957.         if @pubid is NULL
  14958.             begin
  14959.                 raiserror (20026, 11, -1, @publication)
  14960.                 return (1)
  14961.             end
  14962.     end
  14963.  
  14964. if not exists (select * from sysobjects where name='sysmergearticles')
  14965.     return (1)
  14966.     
  14967. begin TRAN
  14968. save TRAN cleanupmetadata
  14969. declare #per_publication CURSOR LOCAL FAST_FORWARD for select pubid
  14970.     from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and name like @publication
  14971. open #per_publication
  14972. fetch #per_publication into @pubid
  14973. while @@fetch_status<>-1
  14974. begin
  14975.     select @pubname=name, @snapshot_ready=snapshot_ready from sysmergepublications where pubid=@pubid
  14976.     if @publication <> '%' and exists (select * from sysmergearticles where pubid<>@pubid and objid in
  14977.         (select objid from sysmergearticles where pubid=@pubid))
  14978.     begin
  14979.         raiserror(21272, 16, -1, @pubname)
  14980.         goto FAILURE
  14981.     end
  14982.  
  14983.     /* Only do this when snapshot has been ran before this operation */
  14984.     if @snapshot_ready>0
  14985.     begin
  14986.         /* If there are any inprocess generations defer the cleanup of metadata */
  14987.         if exists (select top 1 guidsrc from dbo.MSmerge_genhistory h
  14988.             where    guidlocal='00000000-0000-0000-0000-000000000000'  -- incomplete gen
  14989.                 and generation not in (select gen_cur from sysmergearticles)  -- not a local incomplete gen
  14990.                 and coldate in (select login_time from master..sysprocesses)  -- not a gen that currently receives replica updates from another db
  14991.                 and h.art_nick in (select nickname from sysmergearticles where pubid = @pubid)) -- generations relevant to current publication 
  14992.             begin
  14993.                 RAISERROR(21503, 16, -1)
  14994.                 close #per_publication
  14995.                 deallocate #per_publication
  14996.                 goto FAILURE
  14997.             end
  14998.         if LOWER(@reinitialize_subscriber collate SQL_Latin1_General_CP1_CS_AS)='true'        
  14999.         begin
  15000.             -- backward-comp-level is bump'd up by calling this stored procedure            
  15001.             exec @retcode = sp_MSreinitmergepublication @pubname
  15002.             if @@ERROR<>0 or @retcode<>0
  15003.             begin
  15004.                 close #per_publication
  15005.                 deallocate #per_publication
  15006.                 goto FAILURE
  15007.             end
  15008.  
  15009.             update sysmergepublications set snapshot_ready=2 where pubid=@pubid
  15010.             if @@ERROR<>0
  15011.             begin
  15012.                 close #per_publication
  15013.                 deallocate #per_publication
  15014.                 goto FAILURE
  15015.             end
  15016.         end
  15017.         else
  15018.         begin
  15019.             raiserror(21355, 10, -1,@publication)
  15020.             exec @retcode=sp_MSBumpupCompLevel @pubid, 30 --SP2 subscribers support this, but do not propagate
  15021.             if @@ERROR<>0 or @retcode<>0
  15022.             begin
  15023.                 close #per_publication
  15024.                 deallocate #per_publication
  15025.                 goto FAILURE
  15026.             end
  15027.  
  15028.             select @schemaversion = schemaversion from sysmergeschemachange
  15029.             if (@schemaversion is NULL)
  15030.             set @schemaversion = 1
  15031.             else
  15032.                 select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  15033.             set @schemaguid = newid()
  15034.             set @artid = newid()
  15035.             set @schematype = 16 /* metadata cleanup */
  15036.             select @schematext = 'exec dbo.sp_MScleanup_metadata '+ '''' + convert(nchar(36),@pubid) + '''' 
  15037.             exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  15038.             if @@ERROR<>0 or @retcode<>0 
  15039.             begin
  15040.                 close #per_publication
  15041.                 deallocate #per_publication
  15042.                 goto FAILURE            
  15043.             end
  15044.             
  15045.         end
  15046.     end
  15047.     set @make_generation = 1
  15048.     fetch next from #per_publication into @pubid
  15049. end
  15050. close #per_publication
  15051. deallocate #per_publication
  15052. COMMIT TRAN
  15053.  
  15054. if @publication = '%'
  15055.     begin
  15056.         set @pubid = NULL
  15057.     end
  15058. else
  15059.     begin
  15060.         select @pubid = pubid from sysmergepublications 
  15061.             where name = @publication
  15062.     end
  15063.  
  15064.     exec @retcode = dbo.sp_MScleanup_metadata @pubid
  15065.     if @@ERROR <> 0 or @retcode <> 0
  15066.            goto FAILURE
  15067. if @make_generation = 1
  15068.     begin
  15069.         execute @retcode = dbo.sp_MSmakegeneration 
  15070.         if @@ERROR <> 0 or @retcode <> 0
  15071.                goto FAILURE
  15072.     end
  15073. return (0)
  15074. FAILURE:
  15075.     if @@TRANCOUNT > 0
  15076.     begin
  15077.         ROLLBACK TRANSACTION cleanupmetadata
  15078.         COMMIT TRANSACTION
  15079.     end
  15080.     return (1)
  15081.  
  15082. GO
  15083.  
  15084. exec dbo.sp_MS_marksystemobject sp_mergecleanupmetadata
  15085. go
  15086. grant execute on dbo.sp_mergecleanupmetadata to public
  15087. go
  15088.  
  15089.  
  15090. raiserror('Creating procedure sp_MScleanup_conflict_table', 0,1)
  15091. GO
  15092. /*
  15093. ** This stored procedure is to periodically check and cleanup all the conflict entries 
  15094. ** in conflict tables that has been there longer than the value of conflict_retention in
  15095. ** days. 
  15096. */
  15097.  
  15098. create procedure sp_MScleanup_conflict_table
  15099. AS
  15100. BEGIN
  15101.     declare    @retcode            int
  15102.     declare @pubid                uniqueidentifier
  15103.     declare    @conflict_retention    int
  15104.             ,@conflict_table    sysname
  15105.             ,@cmd                nvarchar(4000)
  15106.             ,@tranpubid            int
  15107.  
  15108.     /*
  15109.     ** Security Check
  15110.     */
  15111.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  15112.     IF @@ERROR <> 0 or @retcode <> 0
  15113.         return (1)
  15114.  
  15115.     --
  15116.     -- merge cleanup
  15117.     --
  15118.     if exists (select * from sysobjects where name = 'sysmergepublications')
  15119.     begin
  15120.         declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT pubid, conflict_retention
  15121.             from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and conflict_retention>0
  15122.         open PC
  15123.         fetch PC into @pubid, @conflict_retention
  15124.         while (@@fetch_status<>-1)
  15125.         begin
  15126.             exec @retcode = sp_MScleanup_conflict @pubid, @conflict_retention
  15127.             if @@ERROR<>0 or @retcode<>0
  15128.             begin
  15129.                 close PC
  15130.                 deallocate PC
  15131.                 return (1)
  15132.             end
  15133.             fetch next from PC into  @pubid, @conflict_retention
  15134.         end
  15135.         close PC
  15136.         deallocate PC
  15137.     end
  15138.  
  15139.     --
  15140.     -- tran cleanup
  15141.     --
  15142.     if (EXISTS (select * from sysobjects where name = 'syspublications'))
  15143.     begin
  15144.         --
  15145.         -- do for each conflict table in each publication
  15146.         --
  15147.         declare hCftTab cursor LOCAL FAST_FORWARD for
  15148.             select a.pubid, a.conflict_retention, OBJECT_NAME(c.conflict_tableid)
  15149.             from (syspublications as a join sysarticles as b on a.pubid = b.pubid)
  15150.                 join sysarticleupdates as c on c.artid = b.artid and c.pubid = b.pubid
  15151.             where a.allow_queued_tran = 1 and a.conflict_retention>0
  15152.  
  15153.         open hCftTab
  15154.         fetch hCftTab into @tranpubid, @conflict_retention, @conflict_table
  15155.         while (@@fetch_status != -1)
  15156.         begin
  15157.             --
  15158.             -- delete the expired messages
  15159.             --
  15160.             select @cmd = 'delete ' + quotename(master.dbo.fn_MSgensqescstr(@conflict_table)) collate database_default + 
  15161.                 ' where datediff(dd, getdate(), insertdate) > ' + 
  15162.                 cast(@conflict_retention as nvarchar(10)) +
  15163.                 ' and pubid = ' + cast(@tranpubid as nvarchar(10))
  15164.  
  15165.             execute (@cmd)
  15166.             if (@@error != 0)
  15167.             begin
  15168.                 close hCftTab
  15169.                 deallocate hCftTab
  15170.                 return 1                
  15171.             end
  15172.                 
  15173.             --
  15174.             -- Get next conflict table to clean
  15175.             --
  15176.             fetch hCftTab into @tranpubid, @conflict_retention, @conflict_table
  15177.         end
  15178.  
  15179.         --
  15180.         -- close cursor
  15181.         --
  15182.         close hCftTab
  15183.         deallocate hCftTab
  15184.     end
  15185.  
  15186.     --
  15187.     -- all done 
  15188.     --
  15189.     return 0
  15190. END
  15191. GO
  15192. exec dbo.sp_MS_marksystemobject sp_MScleanup_conflict_table
  15193. go
  15194.  
  15195. raiserror('Creating procedure sp_validatemergesubscription', 0,1)
  15196. GO
  15197.  
  15198. CREATE PROCEDURE sp_validatemergesubscription
  15199.     (@publication            sysname,
  15200.      @subscriber            sysname,
  15201.      @subscriber_db            sysname,
  15202.      @level                    tinyint
  15203.      ) AS
  15204.      
  15205.     declare @subscriber_srvid        int
  15206.     declare @retcode                int
  15207.     declare @pubid                    uniqueidentifier
  15208.     /*
  15209.     ** Security Check
  15210.     */
  15211.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  15212.     IF @@ERROR <> 0 or @retcode <> 0
  15213.         return (1)
  15214.  
  15215.     /* make sure current database is enabled for merge replication */
  15216.     exec @retcode=dbo.sp_MSCheckmergereplication
  15217.     if @@ERROR<>0 or @retcode<>0
  15218.         return (1)
  15219.  
  15220.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber)
  15221.  
  15222.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  15223.     if @pubid is NULL
  15224.         begin
  15225.             raiserror (20026, 16, -1, @publication)
  15226.             return (1)
  15227.         end
  15228.     if @level <1 or @level > 3
  15229.         begin
  15230.             raiserror(21184, 16, -1, '@level', '1', '2','3')
  15231.             return (1)
  15232.         end
  15233.  
  15234.     if not exists (select * from sysmergesubscriptions where pubid=@pubid and db_name=@subscriber_db and srvid=@subscriber_srvid)
  15235.         begin
  15236.             raiserror(14055, 16, -1)
  15237.             return (1)
  15238.         end
  15239.  
  15240.     update sysmergesubscriptions set validation_level=@level where pubid=@pubid and db_name=@subscriber_db and srvid=@subscriber_srvid
  15241.     if @@ERROR<>0
  15242.         return (1)
  15243.     return (0)
  15244.  
  15245. go
  15246. exec dbo.sp_MS_marksystemobject sp_validatemergesubscription
  15247. go
  15248. grant exec on dbo.sp_validatemergesubscription to public
  15249. go
  15250.  
  15251. raiserror('Creating procedure sp_validatemergepublication', 0,1)
  15252. GO
  15253.  
  15254. CREATE PROCEDURE sp_validatemergepublication
  15255.     (@publication            sysname,
  15256.      @level                    tinyint
  15257.      ) AS
  15258.      
  15259.     declare @artid                  uniqueidentifier
  15260.     declare @schematype             int
  15261.     declare @schemaversion          int
  15262.     declare @schemaguid             uniqueidentifier
  15263.     declare @schematext                nvarchar
  15264.     declare @retcode                int
  15265.     declare @pubid                    uniqueidentifier
  15266.     /*
  15267.     ** Security Check
  15268.     */
  15269.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  15270.     IF @@ERROR <> 0 or @retcode <> 0
  15271.         return (1)
  15272.  
  15273.     /* make sure current database is enabled for merge replication */
  15274.     exec @retcode=dbo.sp_MSCheckmergereplication
  15275.     if @@ERROR<>0 or @retcode<>0
  15276.         return (1)
  15277.  
  15278.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  15279.     if @pubid is NULL
  15280.         begin
  15281.             raiserror (20026, 16, -1, @publication)
  15282.             return (1)
  15283.         end
  15284.     if @level <1 or @level > 3
  15285.         begin
  15286.             raiserror(21184, 16, -1, '@level', '1', '2','3')
  15287.             return (1)
  15288.         end
  15289.  
  15290.     raiserror(21356, 10, -1, @publication)
  15291.     exec @retcode=sp_MSBumpupCompLevel @pubid, 30 
  15292.     if @@ERROR<>0 or @retcode<>0        
  15293.         return (1)
  15294.  
  15295.     select @schemaversion = schemaversion from sysmergeschemachange
  15296.     if (@schemaversion is NULL)
  15297.         set @schemaversion = 1
  15298.     else
  15299.         select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  15300.         set @schemaguid = newid()
  15301.         set @artid = newid()
  15302.         set @schematype = 66 /* publication wide validation */
  15303.         select @schematext = convert(nvarchar, @level)        
  15304.         exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext
  15305.         if @@ERROR<>0 or @retcode<>0
  15306.             return (1)
  15307.     return (0)
  15308. go
  15309. exec dbo.sp_MS_marksystemobject sp_validatemergepublication
  15310. go
  15311. grant exec on dbo.sp_validatemergepublication to public
  15312. go
  15313.  
  15314. raiserror('Creating procedure sp_MScleanup_conflict', 0,1)
  15315. GO
  15316.  
  15317. create procedure sp_MScleanup_conflict
  15318. @pubid                    uniqueidentifier,
  15319. @conflict_retention    int = NULL
  15320. AS
  15321.     declare @pubname            sysname
  15322.     declare @valid_date            datetime
  15323.     declare @conflict_table        sysname
  15324.     declare @conflict_id        int
  15325.     declare @retention_string        nvarchar(100)
  15326.     declare @pubidstr            nvarchar(100)
  15327.     declare @retcode            int
  15328.     
  15329.     --if no conflict_retention value is specified, query local table and find out.
  15330.     if @conflict_retention is NULL
  15331.         select @conflict_retention=conflict_retention from sysmergepublications where pubid=@pubid
  15332.  
  15333.     --do not do any cleanup if conflict retention value is 0
  15334.     else if @conflict_retention = 0
  15335.         return (0)
  15336.  
  15337.     select @pubname=name from sysmergepublications where pubid=@pubid
  15338.     select @pubidstr = convert(nvarchar(40), @pubid)
  15339.     select @valid_date = dateadd(day, -@conflict_retention, getdate())
  15340.     select @retention_string = convert(nvarchar, @conflict_retention)
  15341.     /*
  15342.     ** Security Check
  15343.     */
  15344.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  15345.     IF @@ERROR <> 0 or @retcode <> 0
  15346.         return (1)
  15347.  
  15348.  
  15349.     if exists (select name from syscolumns where name='create_time' and id = object_id('MSmerge_delete_conflicts'))
  15350.     begin
  15351.         delete from MSmerge_delete_conflicts where create_time < @valid_date and pubid=@pubid
  15352.         if @@ERROR<>0
  15353.             return (1)
  15354.     end
  15355.     
  15356.     declare AC CURSOR LOCAL FAST_FORWARD for select conflict_table from sysmergearticles where pubid=@pubid
  15357.     open AC
  15358.     fetch AC into @conflict_table
  15359.     while (@@fetch_status<>-1)
  15360.     begin
  15361.         if @conflict_table is NOT null
  15362.             begin
  15363.  
  15364.             select @conflict_id = object_id(@conflict_table)
  15365.             select @conflict_table=QUOTENAME(@conflict_table)
  15366.             /*
  15367.             ** Upgrade conflict table so that it can get cleaned up later on
  15368.             */
  15369.             if @conflict_id is not NULL and not exists (select name from syscolumns where name='MSrepl_create_time' and id=@conflict_id)
  15370.                     begin
  15371.                         exec ('alter table ' + @conflict_table + ' add MSrepl_create_time datetime not NULL default getdate() ')
  15372.                         if @@ERROR<>0
  15373.                             goto FAILURE
  15374.                     end
  15375.  
  15376.             if @conflict_id is not NULL and @retention_string is not NULL and exists (select name from syscolumns where name='MSrepl_create_time' and id=@conflict_id)
  15377.                     begin
  15378.                         exec ('delete from ' + @conflict_table + ' where datediff(dd, MSrepl_create_time, getdate()) > ' + @retention_string + ' and pubid = ''' + @pubidstr + '''')
  15379.                         if @@ERROR<>0
  15380.                             goto FAILURE
  15381.                     end
  15382.             end
  15383.         fetch next from AC into @conflict_table
  15384.     end
  15385.     close AC
  15386.     deallocate AC
  15387.     return (0)
  15388. FAILURE:
  15389.     close AC
  15390.     deallocate AC
  15391.     return (1)
  15392. GO
  15393. exec dbo.sp_MS_marksystemobject sp_MScleanup_conflict
  15394. go
  15395.  
  15396.  
  15397. raiserror('Creating procedure sp_generatefilters', 0,1)
  15398. GO
  15399.  
  15400. create procedure sp_generatefilters
  15401.     @publication                sysname
  15402.     AS
  15403.     /* Declare  a few variables */
  15404.     declare @pubid  uniqueidentifier
  15405.     declare @art_name sysname
  15406.     declare @object_id  int
  15407.     declare @join_objid int
  15408.     declare @retcode int
  15409.     declare @join_unique int
  15410.     declare @distance int
  15411.     
  15412.     /*
  15413.     ** Security Check
  15414.     */
  15415.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  15416.     IF @@ERROR <> 0 or @retcode <> 0
  15417.         return (1)
  15418.  
  15419.     /*
  15420.     ** Parameter Check: @publication.
  15421.     ** The @publication id cannot be NULL and must conform to the rules
  15422.     ** for identifiers.
  15423.     */   
  15424.         
  15425.     if @publication is NULL
  15426.         begin
  15427.             raiserror (14043, 16, -1, '@publication')
  15428.             return (1)
  15429.         end
  15430.     /*
  15431.     ** Get the pubid and make sure the publication exists
  15432.     */
  15433.     select @pubid = pubid from sysmergepublications 
  15434.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  15435.     if @pubid is NULL
  15436.         begin
  15437.             raiserror (20026, 16, -1, @publication)
  15438.             return (1)
  15439.         end
  15440.  
  15441.     /* Set up some temp tables to help keep track of what to process */
  15442.     create table #filtered (object_id int NOT NULL, distance int NOT NULL)
  15443.     create table #unfiltered (object_id int NOT NULL, art_name sysname collate database_default not null)
  15444.  
  15445.     /* Do initial population of temp tables */
  15446.     insert into #filtered (object_id, distance) select objid, 0 from sysmergearticles where
  15447.         pubid = @pubid and len(subset_filterclause) > 0
  15448.     insert into #unfiltered (object_id, art_name) select objid, name from sysmergearticles
  15449.         where pubid = @pubid and objid not in (select object_id from #filtered)
  15450.  
  15451.     /* remove self-referencing tables from #unfiltered as we should not try to filter them */
  15452.     delete from #unfiltered where object_id in
  15453.             (select rkeyid from sysreferences where rkeyid = fkeyid)
  15454.     select @distance = min(distance) from #filtered f, sysreferences r, #unfiltered u where
  15455.         (f.object_id = r.rkeyid and r.fkeyid = u.object_id) or
  15456.         (u.object_id = r.rkeyid and r.fkeyid = f.object_id)
  15457.         
  15458.     /* Look for something in sysreferences to add a join filter for */
  15459.     select @join_unique = 1, @object_id = fkeyid, @join_objid = rkeyid, @art_name = art_name
  15460.         from sysreferences r, #unfiltered u where r.fkeyid = u.object_id and
  15461.         r.rkeyid in (select object_id from #filtered where distance = @distance) 
  15462.  
  15463.     if @art_name is null
  15464.         select  @join_unique = 0, @object_id = rkeyid, @join_objid = fkeyid, @art_name = art_name
  15465.             from sysreferences r, #unfiltered u where r.rkeyid = u.object_id and
  15466.             r.fkeyid in (select object_id from #filtered where distance = @distance) 
  15467.     while @art_name is not null
  15468.         begin
  15469.         /* Make the join filter corresponding to this relationship */
  15470.         exec @retcode=sp_MSmakejoinfilter @publication, @art_name, @object_id, @join_objid, @join_unique
  15471.         if @@ERROR<>0 or @retcode<>0 return (1)
  15472.         /* Move row from #unfiltered to #filtered */
  15473.         insert into #filtered (object_id, distance) values (@object_id, @distance + 1)
  15474.         delete from #unfiltered where object_id = @object_id
  15475.         
  15476.         /* See if any more that can be added */
  15477.         select @distance = min(distance) from #filtered f, sysreferences r, #unfiltered u where
  15478.             (f.object_id = r.rkeyid and r.fkeyid = u.object_id) or
  15479.             (u.object_id = r.rkeyid and r.fkeyid = f.object_id)
  15480.         set @art_name = NULL
  15481.         select @join_unique = 1, @object_id = fkeyid, @join_objid = rkeyid, @art_name = art_name
  15482.             from sysreferences r, #unfiltered u where r.fkeyid = u.object_id and
  15483.             r.rkeyid in (select object_id from #filtered where distance = @distance) 
  15484.         if @art_name is null
  15485.             select  @join_unique = 0, @object_id = rkeyid, @join_objid = fkeyid, @art_name = art_name
  15486.                 from sysreferences r, #unfiltered u where r.rkeyid = u.object_id and
  15487.                 r.fkeyid in (select object_id from #filtered where distance = @distance) 
  15488.         end
  15489.     return (0)
  15490. go
  15491.             
  15492. exec dbo.sp_MS_marksystemobject sp_generatefilters
  15493. go
  15494.  
  15495. grant execute on dbo.sp_generatefilters to public
  15496. go
  15497.  
  15498. /*
  15499. ** Name :       sp_MShelpmergeconflictcounts
  15500. ** Description: This sp returns the count of conflicts (from MSmerge_delete_conflicts and 
  15501. **              each conflict table) in each publication. Results can optionally be filtered
  15502. **                to include only a single publication. Results are always ordered by article
  15503. **                name. Only articles with non-zero conflict counts are returned.
  15504. ** Parameters:  1. Publication Name( sysname; default '%'==ALL PUBLICATIONS)
  15505. ** Output Result Set has the following structure 
  15506. **  ----------------------------------------------------------------------------------
  15507. **      Name                Datatype                Description
  15508. **  ----------------------------------------------------------------------------------
  15509. **  a. article                (sysname)            Article name
  15510. **  b. conflict_table        (sysname)            Associated conflict table
  15511. **  c. guidcolname            (sysname)            Article's rowguidcol name
  15512. **  d. centralized_conflicts(integer)            Centralized (1) or Decentralized (0) 
  15513. **                                                conflicts specified by the article
  15514. **  e. conflict_ucount        (integer)           Count of (update) conflicts in the 
  15515. **                                                conflict table for this article
  15516. **  f. conflicts_dcount        (integer)           Count of (delete) conflicts in the 
  15517. **                                                MSmerge_delete_conflicts table for this article
  15518. */
  15519. raiserror('Creating procedure sp_MShelpmergeconflictcounts', 0,1)
  15520. GO
  15521.  
  15522. create procedure sp_MShelpmergeconflictcounts ( 
  15523.     @publication_name sysname = '%' ,
  15524.     @publisher        sysname = NULL,
  15525.     @publisher_db    sysname = NULL)
  15526. as 
  15527. begin
  15528.  
  15529.     set nocount on 
  15530.  
  15531.     declare    @aname         sysname
  15532.     declare    @cmd         nvarchar(2000) 
  15533.     declare    @conflict_table sysname 
  15534.     declare    @count         integer
  15535.     declare @pubid          uniqueidentifier
  15536.     declare @pubidstr       nvarchar(38)
  15537.  
  15538.     if @publisher IS NULL
  15539.         select @publisher = @@SERVERNAME
  15540.         
  15541.     if @publisher_db IS NULL
  15542.         select @publisher_db = db_name()
  15543.  
  15544.     if @publication_name <> '%'
  15545.         begin
  15546.             /*
  15547.             ** Parameter Check:  @publication.
  15548.             ** Make sure that the publication exists.
  15549.             */
  15550.             select @pubid = pubid from sysmergepublications 
  15551.                 where name = @publication_name and 
  15552.                     LOWER(publisher) = LOWER(@publisher) and
  15553.                     publisher_db = @publisher_db
  15554.             if @pubid IS NULL
  15555.                 BEGIN
  15556.                     RAISERROR (20026, 16, -1, @publication_name)
  15557.                     RETURN (1)
  15558.                 END
  15559.             set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' 
  15560.         end
  15561.  
  15562.     -- make sure current db has merge publishing tables (true on both pub and sub)
  15563.     if not exists ( select * from sysobjects where name = 'sysmergearticles')
  15564.     begin
  15565.         raiserror( 18757, 16, -1 )
  15566.         return(1)
  15567.     end
  15568.  
  15569.     -- allow null conflict table name to handle case where there are delete conflicts but no update conflicts
  15570.     create table #result_list ( article sysname collate database_default, source_object sysname collate database_default, conflict_table sysname collate database_default null, guidcolname sysname collate database_default, centralized_conflicts integer, conflicts_ucount integer, conflicts_dcount integer )
  15571.     create table #conflict_list ( article_name sysname collate database_default, conflicts_ucount integer, conflicts_dcount integer )
  15572.     create table #update_list ( article_name sysname collate database_default, conflicts_ucount integer )
  15573.  
  15574.     -- get delete counts
  15575.     if ( @publication_name = '%' )
  15576.         declare hCdcount CURSOR LOCAL FAST_FORWARD fast_forward for 
  15577.             select distinct a.name 
  15578.                 from MSmerge_delete_conflicts d
  15579.                 inner join sysmergepublications p on p.pubid = d.pubid
  15580.                 inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
  15581.     else
  15582.         declare hCdcount CURSOR LOCAL FAST_FORWARD fast_forward for 
  15583.             select distinct a.name 
  15584.                 from MSmerge_delete_conflicts d
  15585.                 inner join sysmergepublications p on p.pubid = d.pubid
  15586.                 inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
  15587.                 where p.pubid = @pubid
  15588.     open hCdcount
  15589.     fetch hCdcount into @aname
  15590.     while ( @@fetch_status <> -1 )
  15591.     begin
  15592.  
  15593.         select @cmd = 'select N''' + @aname + ''', 0, count(*) 
  15594.                 from MSmerge_delete_conflicts d
  15595.                     inner join sysmergepublications p on p.pubid = d.pubid
  15596.                     inner join sysmergearticles a on a.pubid = p.pubid and a.nickname = d.tablenick
  15597.                 where a.name = N''' + @aname + ''' '
  15598.  
  15599.         if ( @publication_name <> '%' ) 
  15600.             select @cmd = @cmd + ' and p.pubid = ' + @pubidstr
  15601.  
  15602.         insert #conflict_list ( article_name, conflicts_ucount, conflicts_dcount )
  15603.             exec ( @cmd )
  15604.  
  15605.         fetch hCdcount into @aname
  15606.     end
  15607.     close hCdcount
  15608.     deallocate hCdcount
  15609.  
  15610.     -- get update counts
  15611.     if ( @publication_name = '%' )
  15612.         declare hCucount CURSOR LOCAL FAST_FORWARD fast_forward for 
  15613.             select distinct a.name, a.conflict_table
  15614.                 from sysmergepublications p
  15615.                 inner join sysmergearticles a on a.pubid = p.pubid
  15616.             where a.conflict_table is not null
  15617.     else
  15618.         declare hCucount CURSOR LOCAL FAST_FORWARD fast_forward for 
  15619.             select distinct a.name, a.conflict_table
  15620.                 from sysmergepublications p
  15621.                 inner join sysmergearticles a on a.pubid = p.pubid
  15622.             where a.conflict_table is not null
  15623.                   and p.pubid = @pubid
  15624.     open hCucount
  15625.     fetch hCucount into @aname, @conflict_table
  15626.     while ( @@fetch_status <> -1 )
  15627.     begin
  15628.         select @cmd = N'select N''' + @aname + N''', count(*) from ' + QUOTENAME( @conflict_table ) + N' ct inner join sysmergepublications p on p.pubid = ct.pubid '
  15629.  
  15630.         if ( @publication_name <> '%' ) 
  15631.             select @cmd = @cmd + ' where p.name = N''' + @publication_name + ''''
  15632.  
  15633.         insert #update_list ( article_name, conflicts_ucount )
  15634.             exec( @cmd )
  15635.  
  15636.         fetch hCucount into @aname, @conflict_table
  15637.     end
  15638.     close hCucount
  15639.     deallocate hCucount
  15640.  
  15641.     update #conflict_list set conflicts_ucount = isnull( ul.conflicts_ucount, 0 )
  15642.         from #conflict_list cl
  15643.         inner join #update_list ul on ul.article_name = cl.article_name
  15644.  
  15645.     delete #update_list 
  15646.         from #update_list ul 
  15647.         inner join #conflict_list cl on ul.article_name = cl.article_name
  15648.  
  15649.     insert #conflict_list
  15650.         select *, 0 from #update_list where conflicts_ucount > 0
  15651.  
  15652.     drop table #update_list
  15653.     select @cmd = N'select distinct t.article_name, N'''' + quotename(user_name( o.uid )) + ''.'' + quotename(o.name) + '''',' + ' a.conflict_table, c.name, p.centralized_conflicts, t.conflicts_ucount, t.conflicts_dcount
  15654.             from #conflict_list t
  15655.                 inner join sysmergearticles a on a.name = t.article_name
  15656.                 inner join sysmergepublications p on p.pubid = a.pubid
  15657.                 inner join sysobjects o on o.id = a.objid 
  15658.                 inner join syscolumns c on c.id = o.id and ColumnProperty (o.id, c.name, ''IsRowGuidCol'') = 1
  15659.             where (t.conflicts_ucount > 0 or t.conflicts_dcount > 0) and a.conflict_table is NOT NULL'
  15660.  
  15661.     insert #result_list
  15662.         exec ( @cmd )        
  15663.     if ( @@error <> 0 )
  15664.         return (1)
  15665.  
  15666.     drop table #conflict_list
  15667.  
  15668.     select * from #result_list
  15669.     drop table #result_list
  15670.  
  15671. return (0)
  15672. end
  15673. go
  15674.  
  15675. exec dbo.sp_MS_marksystemobject sp_MShelpmergeconflictcounts
  15676. go
  15677.  
  15678. grant execute on dbo.sp_MShelpmergeconflictcounts to public
  15679. go
  15680.  
  15681.  
  15682. /*
  15683. ** Name :       sp_MShelpmergeconflictpublications
  15684. ** Description: This sp returns a list of merge publications in the current database 
  15685. **                that may have conflicts.
  15686. **                Results are always ordered by publication name.
  15687. ** Output Result Set has the following structure 
  15688. **  ----------------------------------------------------------------------------------
  15689. **      Name                Datatype                Description
  15690. **  ----------------------------------------------------------------------------------
  15691. **  a. publication            (sysname)                Publication name
  15692. **    b. merge_pub_id            (uniqueidentifier)        Merge publication id
  15693. */
  15694. raiserror('Creating procedure sp_MShelpmergeconflictcpublications', 0,1)
  15695. GO
  15696.  
  15697. create procedure sp_MShelpmergeconflictpublications
  15698. as 
  15699. begin
  15700.  
  15701.     set nocount on 
  15702.  
  15703.     declare @dbname sysname, @cmd nvarchar(200)
  15704.     set @dbname = db_name()
  15705.  
  15706.     -- make sure current db has merge publishing tables (true on both pub and sub)
  15707.     if not exists ( select * from sysobjects where name = 'sysmergepublications')
  15708.     begin
  15709.         raiserror( 18757, 16, -1 )
  15710.         return(1)
  15711.     end
  15712.  
  15713.     -- unlike tran, all merge publications are updateable, so just return all
  15714.     set @cmd = 'select name, pubid, publisher, publisher_db from ' + @dbname + '.dbo.sysmergepublications order by name'
  15715.     exec( @cmd )
  15716.  
  15717.      return (0)
  15718.  
  15719. end
  15720. go
  15721.  
  15722. exec dbo.sp_MS_marksystemobject sp_MShelpmergeconflictpublications
  15723. go
  15724.  
  15725. grant execute on dbo.sp_MShelpmergeconflictpublications to public
  15726. go
  15727.  
  15728. create procedure sp_MSclearcolumnbit
  15729. @pubid            uniqueidentifier,
  15730. @artid            uniqueidentifier,
  15731. @column_name    sysname
  15732. as 
  15733.  
  15734. declare @tablename        sysname
  15735. declare @colid            int
  15736. declare @in_use            bit
  15737. declare @objid            int
  15738. declare @columns         varbinary(128)
  15739. declare @local_repid    uniqueidentifier
  15740. declare @publish        int
  15741. set nocount on 
  15742.  
  15743. set @publish        = 0x4000
  15744. set @in_use=0
  15745. set @local_repid    = NULL
  15746.  
  15747. select @tablename = object_name(objid), @objid=objid from sysmergearticles where artid=@artid and pubid=@pubid
  15748.  
  15749. select @colid=colid from syscolumns where id=@objid and name=@column_name
  15750.  
  15751. select top 1 @local_repid=pubid from sysmergearticles where artid=@artid and pubid<>@pubid order by pubid ASC
  15752. if @local_repid is NULL
  15753. begin
  15754.     update syscolumns set colstat = colstat & ~@publish where id=@objid and colid=@colid
  15755.     if @@ERROR<>0
  15756.         return (1)
  15757.     return (0)
  15758. end
  15759. while @local_repid is not NULL and @in_use=0
  15760. begin
  15761.     select @columns = columns from sysmergearticles where pubid=@local_repid and artid=@artid
  15762.     exec @in_use = sp_MStestbit @bm=@columns, @coltotest=@colid
  15763.     set @local_repid    = NULL
  15764.     select top 1 @local_repid=pubid from sysmergearticles where artid=@artid and pubid>@local_repid order by pubid ASC
  15765. end
  15766. if @in_use=0
  15767. begin
  15768.     update syscolumns set colstat = colstat & ~@publish where id=@objid and colid=@colid
  15769.     if @@ERROR<>0
  15770.         return (1)
  15771. end
  15772. return (0)
  15773. go
  15774.  
  15775. exec dbo.sp_MS_marksystemobject sp_MSclearcolumnbit
  15776. go
  15777.  
  15778. grant execute on dbo.sp_MSclearcolumnbit to public
  15779. go
  15780.  
  15781. /*
  15782. ** Name :       sp_helpmergearticleconflicts
  15783. ** Description: This sp returns the articles in the publication that have conflicts.
  15784. **              Optionally if the publication is not specified, all articles in the 
  15785. **              database that have conflicts is returned.
  15786. ** Parameters:  Publication Name( default NULL)
  15787. ** Output Result Set has the following columns
  15788. **              publication, article, source_object, conflict_table, guidcolname
  15789. */
  15790. raiserror('Creating procedure sp_helpmergearticleconflicts', 0,1)
  15791. GO
  15792. CREATE PROCEDURE sp_helpmergearticleconflicts(
  15793.     @publication    sysname = '%',
  15794.     @publisher        sysname = NULL,
  15795.     @publisher_db    sysname = NULL
  15796.     )
  15797. as
  15798.     set nocount on
  15799.     declare @pubid          uniqueidentifier
  15800.     declare @cmd            nvarchar(4000)
  15801.  
  15802.     declare @retcode        int
  15803.     declare @nickname        int
  15804.     declare @retcode2         int
  15805.     declare @name            sysname
  15806.     declare @source_owner    sysname
  15807.     declare @source_object    sysname
  15808.     declare @conflict_table    sysname
  15809.     declare @guidcolname        sysname
  15810.     declare @centralized_conflicts int
  15811.     declare @objid            int
  15812.     declare @command        nvarchar(200)
  15813.  
  15814.     if @publisher IS NULL
  15815.         select @publisher = @@SERVERNAME
  15816.         
  15817.     if @publisher_db IS NULL
  15818.         select @publisher_db = db_name()
  15819.  
  15820.     if @publication <> '%'
  15821.         begin
  15822.             /*
  15823.             ** Parameter Check:  @publication.
  15824.             ** Make sure that the publication exists.
  15825.             */
  15826.             select @pubid = pubid from sysmergepublications 
  15827.                 where name = @publication and 
  15828.                     LOWER(publisher) = LOWER(@publisher) and
  15829.                     publisher_db = @publisher_db
  15830.             if @pubid IS NULL
  15831.                 BEGIN
  15832.                     RAISERROR (20026, 16, -1, @publication)
  15833.                     RETURN (1)
  15834.                 END
  15835.         end
  15836.  
  15837.     create table #temp_conflict(article                 sysname collate database_default,
  15838.                                 source_owner            sysname collate database_default,
  15839.                                 source_object            sysname collate database_default,
  15840.                                 conflict_table            sysname collate database_default,
  15841.                                 guidcolname                sysname collate database_default,
  15842.                                 centralized_conflicts    int)     
  15843.  
  15844.     declare #cur_conflict cursor local for 
  15845.         select name, objid, conflict_table, pubid, nickname from sysmergearticles 
  15846.             where conflict_table is not NULL and pubid in (select pubid from sysmergepublications where name like @publication)
  15847.                 for read only
  15848.     open #cur_conflict
  15849.     fetch #cur_conflict into @name, @objid, @conflict_table, @pubid, @nickname
  15850.     while (@@fetch_status <> -1)
  15851.     begin
  15852.         select @source_owner = user_name(uid) from sysobjects where id = @objid
  15853.         select @source_object = object_name (@objid)
  15854.         select @guidcolname = name from syscolumns where id = @objid and ColumnProperty(@objid, name, 'IsRowGuidCol') = 1
  15855.         select @centralized_conflicts = centralized_conflicts from sysmergepublications where pubid = @pubid
  15856.  
  15857.         select @command = 'if exists (select * from ' + QUOTENAME(@conflict_table) + ') select @retcode2 = 1
  15858.                                 else select @retcode2 = 0'
  15859.         EXEC @retcode = dbo.sp_executesql @command, N'@retcode2 int output', @retcode2 output
  15860.         if @retcode <>0
  15861.                 return (1)
  15862.         if @retcode2 = 1 
  15863.         begin
  15864.             insert into #temp_conflict 
  15865.                 values (@name, @source_owner, @source_object, @conflict_table, @guidcolname, @centralized_conflicts)
  15866.         end
  15867.         if EXISTS (select * from MSmerge_delete_conflicts where tablenick = @nickname)
  15868.         begin
  15869.             insert into #temp_conflict
  15870.                 values (@name, @source_owner, @source_object, 'MSmerge_delete_conflicts', @guidcolname, @centralized_conflicts)
  15871.         end
  15872.         fetch #cur_conflict into @name, @objid, @conflict_table, @pubid, @nickname
  15873.     end
  15874.  
  15875.     select * from #temp_conflict order by article
  15876.  
  15877.     drop table #temp_conflict
  15878.     close #cur_conflict
  15879.     deallocate #cur_conflict
  15880. return(0)       
  15881. go
  15882. exec dbo.sp_MS_marksystemobject sp_helpmergearticleconflicts 
  15883. go
  15884.  
  15885. /*
  15886. ** Name :       sp_helpmergeconflictrows
  15887. ** Description: This sp returns the rows in the conflict_table specified. 
  15888. **              Optionally if the publication is specified, all conflicts qualified by the
  15889. **              publication are returned. For instance if the Conflict_Customers table 
  15890. **              has conflict rows for the 'WA' and the 'CA' publication, passing in 
  15891. **              a publication name say 'CA' retrieves conflicts pertaining to the 
  15892. **              'CA' publication.
  15893. ** Parameters:  1. Publication Name( default NULL)
  15894. **              2. Conflict Table Name
  15895. ** Output Result Set has the same structure as the Conflict_<table> i.e the base
  15896. ** table structure with the following additional columns:
  15897. **  ----------------------------------------------------------------------------------
  15898. **      Name                Datatype            Description
  15899. **  ----------------------------------------------------------------------------------
  15900. **  a. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
  15901. **  b. conflict_type        (int)               Code indicating type of conflict
  15902. **                                              UpdateConflict      = 1
  15903. **                                              UploadError         = 2
  15904. **                                              DownloadError       = 3
  15905. **                                              UpdateDeleteConflict= 4
  15906. **                                              ColumnUpdateConflict= 5
  15907. **  c. reason_code          (int)               Error code that may be context sensitive 
  15908. **  d. reason_text          (varchar(720))      Error description that may be context sensitive                                                          
  15909. **  e. pubid                (uniqueidentifier)  Publication identifier
  15910. */
  15911. raiserror('Creating procedure sp_helpmergeconflictrows', 0,1)
  15912. GO
  15913. CREATE PROCEDURE sp_helpmergeconflictrows(
  15914.     @publication    sysname = '%',
  15915.     @conflict_table sysname,
  15916.     @publisher        sysname = NULL,
  15917.     @publisher_db    sysname = NULL
  15918.     
  15919.     )
  15920. as 
  15921.     set nocount on
  15922.     declare @pubid          uniqueidentifier
  15923.     declare @cmd            nvarchar(4000)  
  15924.     declare @pubidstr       nvarchar(38)
  15925.     
  15926.     if @publisher IS NULL
  15927.         select @publisher = @@SERVERNAME
  15928.         
  15929.     if @publisher_db IS NULL
  15930.         select @publisher_db = db_name()
  15931.     select @cmd = 'select * from ' 
  15932.     select @cmd = @cmd + QUOTENAME(@conflict_table)
  15933.     if @publication <> '%'
  15934.         begin
  15935.             /*
  15936.             ** Parameter Check:  @publication.
  15937.             ** Make sure that the publication exists.
  15938.             */
  15939.             select @pubid = pubid from sysmergepublications 
  15940.                 where name = @publication and 
  15941.                     LOWER(publisher) = LOWER(@publisher) and
  15942.                     publisher_db = @publisher_db
  15943.             if @pubid IS NULL
  15944.                 BEGIN
  15945.                     RAISERROR (20026, 16, -1, @publication)
  15946.                     RETURN (1)
  15947.                 END
  15948.  
  15949.             set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' 
  15950.             select @cmd = @cmd + ' where pubid = ' + @pubidstr
  15951.             
  15952.         end
  15953.     exec (@cmd)
  15954.     if (@@error <> 0)
  15955.         RETURN (1)
  15956.     
  15957.     return 0
  15958. go
  15959.  
  15960. exec dbo.sp_MS_marksystemobject sp_helpmergeconflictrows 
  15961. go
  15962.  
  15963. /*
  15964. ** Name :       sp_helpmergedeleteconflictrows
  15965. ** Description: This sp returns the rows in the MSmerge_delete_conflicts specified. 
  15966. **              Optionally if the publication is specified, all conflicts qualified by the
  15967. **              publication are returned. For instance if the MSmerge_delete_conflicts table 
  15968. **              has conflict rows for the 'WA' and the 'CA' publication, passing in 
  15969. **              a publication name say 'CA' retrieves conflicts pertaining to the 
  15970. **              'CA' publication only.
  15971. ** Parameters:  1. Publication Name( default NULL)
  15972. **              2. Source Object Name
  15973. ** Output Result Set has the following structure 
  15974. **  ----------------------------------------------------------------------------------
  15975. **      Name                Datatype                Description
  15976. **  ----------------------------------------------------------------------------------
  15977. **  a. source_object        (nvarchar(386))     Indicates the source object for the delete conflict                                                         
  15978. **  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
  15979. **  c. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
  15980. **  d. conflict_type        (int)               Code indicating type of conflict
  15981. **                                              UpdateConflict      = 1
  15982. **                                              UploadError         = 2
  15983. **                                              DownloadError       = 3
  15984. **                                              UpdateDeleteConflict= 4
  15985. **                                              ColumnUpdateConflict= 5
  15986. **  e. reason_code          (int)               Error code that may be context sensitive 
  15987. **  f. reason_text          (varchar(720))      Error description that may be context sensitive                                                          
  15988. **  g. pubid                (uniqueidentifier)  Publication identifier
  15989. */
  15990. raiserror('Creating procedure sp_helpmergedeleteconflictrows', 0,1)
  15991. GO
  15992.  
  15993. CREATE PROCEDURE sp_helpmergedeleteconflictrows(
  15994.     @publication    sysname = '%',
  15995.     @source_object  nvarchar(386) = NULL,
  15996.     @publisher        sysname = NULL,
  15997.     @publisher_db    sysname = NULL
  15998.     )
  15999. as
  16000.     declare @pubid          uniqueidentifier
  16001.     declare @cmd            nvarchar(4000)  
  16002.     declare @pubidstr       nvarchar(38)
  16003.  
  16004.     if @publisher IS NULL
  16005.         select @publisher = @@SERVERNAME
  16006.         
  16007.     if @publisher_db IS NULL
  16008.         select @publisher_db = db_name()
  16009.     select @cmd = 'select distinct source_object =  user_name(sysobjects.uid) + '
  16010.     select @cmd = @cmd + '''.'''
  16011.     select @cmd = @cmd + ' + sysobjects.name, MSmerge_delete_conflicts.rowguid, MSmerge_delete_conflicts.conflict_type, '
  16012.     select @cmd = @cmd + ' MSmerge_delete_conflicts.reason_code, MSmerge_delete_conflicts.reason_text, '
  16013.     select @cmd = @cmd + ' MSmerge_delete_conflicts.origin_datasource, MSmerge_delete_conflicts.pubid, MSmerge_delete_conflicts.create_time from MSmerge_delete_conflicts, sysmergearticles, sysobjects'  
  16014.     select @cmd = @cmd + ' where sysmergearticles.nickname = MSmerge_delete_conflicts.tablenick and sysobjects.id = sysmergearticles.objid '
  16015.     if @publication <> '%'
  16016.         begin
  16017.             /*
  16018.             ** Parameter Check:  @publication.
  16019.             ** Make sure that the publication exists.
  16020.             */
  16021.             select @pubid = pubid from sysmergepublications 
  16022.                 where name = @publication and 
  16023.                     LOWER(publisher) = LOWER(@publisher) and
  16024.                     publisher_db = @publisher_db
  16025.             if @pubid IS NULL
  16026.                 BEGIN
  16027.                     RAISERROR (20026, 16, -1, @publication)
  16028.                     RETURN (1)
  16029.                 END
  16030.             set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' 
  16031.             select @cmd = @cmd + ' and MSmerge_delete_conflicts.pubid = ' + @pubidstr
  16032.         end
  16033.  
  16034.     if @source_object IS NOT NULL
  16035.         begin
  16036.             declare @object         sysname  
  16037.             declare @owner          sysname  
  16038.             declare @tablenick      int
  16039.             declare @tablenickstr   nvarchar(11)
  16040.             
  16041.             select @object = PARSENAME(@source_object, 1)
  16042.             select @owner = PARSENAME(@source_object, 2)
  16043.             execute dbo.sp_MStablenickname @owner, @object, @tablenick output
  16044.             if @tablenick IS NULL
  16045.                 BEGIN
  16046.                     raiserror (20003, 11, -1, @object)
  16047.                     RETURN (1)
  16048.                 END
  16049.             set @tablenickstr = convert(nchar, @tablenick)
  16050.             select @cmd = @cmd + ' and MSmerge_delete_conflicts.tablenick = '
  16051.             select @cmd = @cmd + @tablenickstr
  16052.         end
  16053.  
  16054.     exec (@cmd)
  16055.     if (@@error <> 0)
  16056.         RETURN (1)
  16057.     
  16058.     return 0
  16059. go
  16060.  
  16061. exec dbo.sp_MS_marksystemobject sp_helpmergedeleteconflictrows 
  16062. go
  16063.  
  16064. /*
  16065. ** Name :       sp_deletemergeconflictrow
  16066. ** Description: This sp deletes the row matching rowguid and origin_datasource
  16067. **              If now rows are left in conflict_table
  16068. **                  --Set the conflict_table property of the article(s) to NULL
  16069. **                  --Drop the conflict table (optionally)
  16070. **              If the conflict_table is specified as NULL, the conflict is assumed
  16071. **              to be a delete conflict and the row matching rowguid and origin_datasource
  16072. **              and source_object is deleted from the MSmerge_delete_conflicts table. The
  16073. **              MSmerge_delete_conflicts table is a system table and is not deleted 
  16074. **              from the database even if it is empty.
  16075. ** Parameters:  
  16076. **  ----------------------------------------------------------------------------------
  16077. **      Name                Datatype                Description
  16078. **  ----------------------------------------------------------------------------------
  16079. **  a. conflict_table       (sysname)           Indicates the conflict table name. If
  16080.                                                 '%' then delete from MSmerge_delete_conflicts
  16081. **  b. source_object        (nvarchar(386))     Source table 
  16082. **  c. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
  16083. **  d. origin_datasource    (varchar(255))      Indicates the origin of the conflict                                                         
  16084. **  e. drop_table_if_empty  (varchar(10))       Flag indicating if the Conflict_<table>
  16085. **                                              is to be dropped if is empty
  16086. */
  16087. raiserror('Creating procedure sp_deletemergeconflictrow', 0,1)
  16088. GO
  16089.  
  16090. CREATE PROCEDURE sp_deletemergeconflictrow(
  16091.     @conflict_table         sysname = '%',
  16092.     @source_object          nvarchar(386) = NULL,
  16093.     @rowguid                uniqueidentifier,
  16094.     @origin_datasource      varchar(255),
  16095.     @drop_table_if_empty    varchar(10) = 'false')
  16096. as
  16097.     declare @retcode        smallint
  16098.     declare @cmd            nvarchar(4000)  
  16099.     declare @rowguidstr     nvarchar(40)
  16100.     declare @object         sysname  
  16101.     declare @owner          sysname  
  16102.     declare @tablenick      int
  16103.     declare @tablenickstr   nvarchar(11)
  16104.  
  16105.  
  16106.     set @rowguidstr = convert(nchar(36), @rowguid)
  16107.  
  16108.     /* Delete conflict from Conflict_<Table> */
  16109.     if @conflict_table <> '%'
  16110.         begin
  16111.             select @cmd = 'delete from '
  16112.             select @cmd = @cmd + quotename(@conflict_table) 
  16113.             select @cmd = @cmd + ' where origin_datasource = '''
  16114.             select @cmd = @cmd + @origin_datasource 
  16115.             select @cmd = @cmd + ''' and rowguidcol = '''
  16116.             select @cmd = @cmd + @rowguidstr
  16117.             select @cmd = @cmd + ''''
  16118.             exec (@cmd)
  16119.             if @@ERROR<>0 return (1)
  16120.  
  16121.             if LOWER(@drop_table_if_empty collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  16122.                 begin
  16123.                     select @cmd = 'if not exists (select 1 from ' 
  16124.                     select @cmd = @cmd + quotename(@conflict_table) 
  16125.                     select @cmd = @cmd + ')'
  16126.                     select @cmd = @cmd + ' update sysmergearticles set ins_conflict_proc = NULL, conflict_table = NULL where conflict_table = ' + quotename(@conflict_table)
  16127.                     exec (@cmd)
  16128.                     if @@ERROR<>0 
  16129.                         return (1)
  16130.                         
  16131.                     select @cmd = 'if not exists (select 1 from ' 
  16132.                     select @cmd = @cmd + quotename(@conflict_table)
  16133.                     select @cmd = @cmd + ')'
  16134.                     select @cmd = @cmd + ' drop table '
  16135.                     select @cmd = @cmd + quotename(@conflict_table)
  16136.                     select @cmd = @cmd + ''
  16137.                     exec (@cmd)
  16138.                     if @@ERROR<>0 return (1)
  16139.                 end
  16140.         end
  16141.     /* Delete conflict from MSmerge_delete_conflicts */
  16142.     else
  16143.         begin
  16144.             if @source_object is NULL
  16145.                 begin
  16146.                     raiserror(14043, 16, -1, '@source_object')
  16147.                     return (1)
  16148.                 end
  16149.             select @object = PARSENAME(@source_object, 1)
  16150.             select @owner = PARSENAME(@source_object, 2)
  16151.             execute @retcode=sp_MStablenickname @owner, @object, @tablenick output
  16152.         
  16153.             if @tablenick IS NULL or @@ERROR<>0 or @retcode<>0
  16154.                 BEGIN
  16155.                     raiserror (20003, 11, -1, @object)
  16156.                     RETURN (1)
  16157.                 END
  16158.  
  16159.             set @tablenickstr = convert(nchar, @tablenick)
  16160.  
  16161.             
  16162.             select @cmd = 'delete from MSmerge_delete_conflicts'
  16163.             select @cmd = @cmd + ' where origin_datasource = '''
  16164.             select @cmd = @cmd + @origin_datasource 
  16165.             select @cmd = @cmd + ''' and tablenick = '
  16166.             select @cmd = @cmd + @tablenickstr
  16167.             select @cmd = @cmd + ' and rowguid = '''
  16168.             select @cmd = @cmd + @rowguidstr
  16169.             select @cmd = @cmd + ''''
  16170.             exec (@cmd)
  16171.             if @@ERROR<>0 return (1)
  16172.  
  16173.         end
  16174.  
  16175. go
  16176.  
  16177. exec dbo.sp_MS_marksystemobject sp_deletemergeconflictrow 
  16178. go
  16179.  
  16180. /*
  16181. ** Name :       sp_getmergedeletetype
  16182. ** Description: This sp returns the type of delete
  16183. ** Parameters:  
  16184. **  ----------------------------------------------------------------------------------
  16185. **      Name                Datatype                Description
  16186. **  ----------------------------------------------------------------------------------
  16187. **  a. source_object        (nvarchar(386))     Indicates the source object
  16188. **  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
  16189. **  c. delete_type(OUTPUT)  (int)               Code indicating delete type
  16190. **                                              User Delete     -   1
  16191. **                                              Partial Delete  -   5                                                       
  16192. **                                              System Delete   -   6                                                       
  16193. */
  16194. raiserror('Creating procedure sp_getmergedeletetype', 0,1)
  16195. GO
  16196.  
  16197. CREATE PROCEDURE sp_getmergedeletetype(
  16198.     @source_object  nvarchar (386),
  16199.     @rowguid        uniqueidentifier,
  16200.     @delete_type    int OUTPUT
  16201. )
  16202. as
  16203.     declare @object         sysname  
  16204.     declare @owner          sysname  
  16205.     declare @tablenick      int
  16206.  
  16207.     select @object = PARSENAME(@source_object, 1)
  16208.     select @owner = PARSENAME(@source_object, 2)
  16209.     execute dbo.sp_MStablenickname @owner, @object, @tablenick output
  16210.     if @tablenick IS NULL OR @@ERROR<>0
  16211.         BEGIN
  16212.             raiserror (20003, 11, -1, @object)
  16213.             RETURN (1)
  16214.         END
  16215.  
  16216.     if @rowguid IS NULL 
  16217.         begin
  16218.             raiserror (14027, 11, -1, '@rowguid')
  16219.             return (1)
  16220.         end
  16221.         
  16222.     select @delete_type = type from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick
  16223. go
  16224.  
  16225. exec dbo.sp_MS_marksystemobject sp_getmergedeletetype 
  16226. go
  16227.  
  16228. /*
  16229. ** Name :       sp_mergedummyupdate
  16230. ** Description: This sp does a dummy updates on the given row so that it will be
  16231. **              resent during the next merge.
  16232. * Parameters:   
  16233. **  ----------------------------------------------------------------------------------
  16234. **      Name                Datatype                Description
  16235. **  ----------------------------------------------------------------------------------
  16236. **  a. source_object        (nvarchar(386))     Indicates the source object
  16237. **  b. rowguid              (uniqueidentifier)  Row identifier for the delete conflict
  16238. */
  16239. raiserror('Creating procedure sp_mergedummyupdate', 0,1)
  16240. GO
  16241.  
  16242. CREATE PROCEDURE sp_mergedummyupdate(
  16243.     @source_object  nvarchar (386),
  16244.     @rowguid        uniqueidentifier
  16245. )
  16246. as
  16247.     declare @object         sysname  
  16248.     declare @owner          sysname  
  16249.     declare @tablenick      int
  16250.     declare @tablenickstr   nvarchar(11)
  16251.  
  16252.     select @object = PARSENAME(@source_object, 1)
  16253.     select @owner = PARSENAME(@source_object, 2)
  16254.     execute dbo.sp_MStablenickname @owner, @object, @tablenick output
  16255.     if @tablenick IS NULL or @@ERROR<>0
  16256.         BEGIN
  16257.             raiserror (20003, 11, -1, @object)
  16258.             RETURN (1)
  16259.         END
  16260.     set @tablenickstr = convert(nchar, @tablenick)
  16261.  
  16262.     declare @rowguidstr nvarchar(40)
  16263.     if @rowguid IS NULL 
  16264.         begin
  16265.             raiserror (14043, 11, -1, '@rowguid')
  16266.             return (1)
  16267.         end
  16268.     set @rowguidstr = convert(nchar(36), @rowguid)
  16269.  
  16270.     /* 
  16271.     ** If the row does not exist in the base table, call sp_MSdummyupdate with metadata_type = 1 (tombstone)
  16272.     */
  16273.     exec ('if not exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
  16274.         @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 1')
  16275.  
  16276.     /* 
  16277.     ** If the row exists in the base table and MSmerge_contents , call sp_MSdummyupdate with metadata_type = 2 (contents)
  16278.     */
  16279.     exec ('if exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
  16280.         @rowguidstr + ''' ) and exists (select rowguid from MSmerge_contents where rowguid = ''' +
  16281.         @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 2')
  16282.  
  16283.     /* 
  16284.     ** If the row exists in the base table, but not in MSmerge_contents , call sp_MSdummyupdate with metadata_type = 3 (contents_deferred)
  16285.     */
  16286.     exec ('if exists (select 1 from ' + @source_object + ' where rowguidcol = ''' +
  16287.         @rowguidstr + ''' ) and not exists (select rowguid from MSmerge_contents where rowguid = ''' +
  16288.         @rowguidstr + ''' ) exec dbo.sp_MSdummyupdate ''' + @rowguidstr + ''',' + @tablenickstr + ', 3')
  16289.  
  16290.  
  16291. go
  16292.  
  16293. exec dbo.sp_MS_marksystemobject sp_mergedummyupdate 
  16294. go
  16295.  
  16296. raiserror('Creating procedure sp_addtabletocontents', 0,1)
  16297. GO
  16298.  
  16299. create procedure sp_addtabletocontents 
  16300.     (@table_name sysname,
  16301.      @owner_name sysname = NULL)
  16302. AS
  16303.  
  16304.     declare @qualified_table_name nvarchar(270)
  16305.     declare @tablenick int
  16306.     declare @tablenickstr nvarchar(12)
  16307.     declare @repl_nick int
  16308.     declare @lineage varbinary(249)
  16309.     declare @colv varbinary(2000)
  16310.     declare @coltrack int
  16311.     declare @objid int
  16312.     declare @maxcolid int
  16313.     declare @retcode int
  16314.     declare @gen int
  16315.     
  16316.     set nocount on
  16317.     create table #temp_cont(rowguid uniqueidentifier)
  16318.     execute @retcode = dbo.sp_MSgetreplnick @nickname = @repl_nick output
  16319.     if (@@error <> 0) or @retcode <> 0 or @repl_nick IS NULL 
  16320.         begin
  16321.         RAISERROR (14055, 11, -1)
  16322.         RETURN(1)
  16323.         end                 
  16324.  
  16325.     if @owner_name is NULL
  16326.         begin
  16327.         select @owner_name = user_name(uid) from sysobjects where name = @table_name
  16328.         end
  16329.     set @qualified_table_name = QUOTENAME(@owner_name) + '.' + QUOTENAME(@table_name)
  16330.     
  16331.     set @objid = object_id(@qualified_table_name)
  16332.     if @objid is NULL return (1)
  16333.     select @gen = max(gen_cur), @tablenick = max(nickname), @coltrack = max(column_tracking) from sysmergearticles where objid = @objid
  16334.     if @gen is null
  16335.         set @gen = 0
  16336.     select @maxcolid = max(colid) from syscolumns where id = @objid
  16337.  
  16338.     if @coltrack = 1
  16339.         set @colv = { fn INITCOLVS(@maxcolid, @repl_nick) }
  16340.     else
  16341.         set @colv = NULL
  16342.     set @lineage = { fn UPDATELINEAGE(0x0, @repl_nick, 1) }
  16343.  
  16344.     set @tablenickstr = convert(nchar, @tablenick)
  16345.  
  16346.     exec ('insert into #temp_cont(rowguid) select RowGuidCol from ' + @qualified_table_name + ' where
  16347.             RowGuidCol not in (select rowguid from MSmerge_contents where tablenick = 
  16348.             ' + @tablenickstr + ')')
  16349.  
  16350.     insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1)
  16351.         select @tablenick, rowguid, @gen, @gen, @lineage, @colv from #temp_cont
  16352.  
  16353.     drop table #temp_cont
  16354. GO
  16355. exec dbo.sp_MS_marksystemobject sp_addtabletocontents 
  16356. go
  16357. grant exec on dbo.sp_addtabletocontents to public
  16358. go
  16359.  
  16360.  
  16361.  
  16362.  
  16363.  
  16364. raiserror('Creating procedure sp_MSaddpubtocontents', 0,1)
  16365. GO
  16366.  
  16367. create procedure sp_MSaddpubtocontents 
  16368.     (@publication   sysname)
  16369. AS
  16370.     declare     @pubid  uniqueidentifier
  16371.     declare     @tablenick int
  16372.     declare     @retcode int
  16373.     declare     @objid int
  16374.     declare     @owner sysname
  16375.     declare        @table sysname
  16376.     
  16377.     set nocount on
  16378.     select @pubid = pubid from sysmergepublications 
  16379.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  16380.     if @pubid is NULL
  16381.         begin
  16382.             raiserror (20026, 11, -1, @publication)
  16383.             return (1)
  16384.         end
  16385.     
  16386.     select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid
  16387.  
  16388.     while @tablenick is not null
  16389.         begin
  16390.         select @objid = objid from sysmergearticles where pubid = @pubid and
  16391.             nickname = @tablenick
  16392.         select @owner = user_name(uid) from sysobjects where id = @objid
  16393.         set @table = OBJECT_NAME(@objid)
  16394.         exec @retcode = dbo.sp_addtabletocontents @table, @owner
  16395.         
  16396.         IF @@ERROR <> 0 or @retcode <> 0
  16397.             return (1)
  16398.  
  16399.         select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid and
  16400.                 nickname > @tablenick
  16401.         end
  16402. GO
  16403. exec dbo.sp_MS_marksystemobject sp_MSaddpubtocontents 
  16404. go
  16405. grant exec on dbo.sp_MSaddpubtocontents to public
  16406. go
  16407.  
  16408. raiserror(15339,-1,-1,'sp_MSget_subtypedatasrc')
  16409. GO
  16410. CREATE PROCEDURE sp_MSget_subtypedatasrc
  16411. @subscriber                sysname,
  16412. @distributor            sysname,
  16413. @distribdb                sysname,
  16414. @datasrctype            int OUTPUT,
  16415. @datasrc                sysname OUTPUT
  16416. AS
  16417.     SET NOCOUNT ON
  16418.  
  16419.     DECLARE @provider_name        sysname
  16420.     DECLARE @jet_subscriber     tinyint
  16421.     DECLARE @oledb_subscriber   tinyint
  16422.     DECLARE @oracle_subscriber  tinyint
  16423.     DECLARE @db2universal_subscriber tinyint
  16424.     DECLARE @distproc           nvarchar(300)
  16425.     DECLARE @cmd                 nvarchar(512)
  16426.     
  16427.     set @jet_subscriber = 2   
  16428.     set @oledb_subscriber = 3 
  16429.     set @oracle_subscriber = 5 
  16430.     set @db2universal_subscriber = 6
  16431.     
  16432.     create table #subtype
  16433.     (
  16434.         type tinyint not null,   
  16435.     )
  16436.  
  16437.     create table #server_info 
  16438.     (
  16439.         providername nvarchar(256) collate database_default null,
  16440.         datasource nvarchar(3750) collate database_default null,            -- this column is nvarchar(4000) in sysservers, but we want to avoid info msg
  16441.                                                                             -- from create table when row size > 8060 bytes.
  16442.     )
  16443.  
  16444.     SELECT @distproc = RTRIM(@distributor) + '.' +
  16445.         RTRIM(@distribdb) + '.dbo.sp_executesql'
  16446.  
  16447.     SELECT @cmd = 'select type from MSsubscriber_info where UPPER(subscriber) = ''' + UPPER(@subscriber) + ''' and UPPER(publisher) = ''' + @@servername + ''''
  16448.     
  16449.     insert into #subtype exec @distproc @cmd
  16450.     if (@@error <> 0 or @@rowcount <> 1)
  16451.     begin
  16452.         drop table #subtype
  16453.         drop table #server_info
  16454.         raiserror(14085, 16, -1)
  16455.         return 1
  16456.     end
  16457.     
  16458.     select @datasrctype = type from #subtype
  16459.     
  16460.     SELECT @cmd = 'select providername, datasource from master..sysservers where UPPER(srvname) = ''' + UPPER(@subscriber) + ''''
  16461.     
  16462.     insert into #server_info exec @distproc @cmd
  16463.     if (@@error <> 0 or @@rowcount <> 1)
  16464.     begin
  16465.         drop table #subtype
  16466.         drop table #server_info
  16467.         raiserror(14085, 16, -1)
  16468.         return 1
  16469.     end
  16470.     
  16471.     select @datasrc = datasource, @provider_name =  providername from #server_info
  16472.     
  16473.     /*
  16474.     ** Jet and Oracle subscribers are actually added to MSsubscriber_info as OLE DB subscribers,
  16475.     ** since they can be used in transactional replication also.
  16476.     ** Map the type to Jet or Oracle based on OLE DB provider name.
  16477.     */
  16478.     
  16479.     if (@datasrctype = @oledb_subscriber) 
  16480.     BEGIN
  16481.         if (upper(@provider_name collate SQL_Latin1_General_CP1_CS_AS) = 'MICROSOFT.JET.OLEDB.4.0')
  16482.             select @datasrctype = @jet_subscriber
  16483.         else if (upper(@provider_name collate SQL_Latin1_General_CP1_CS_AS) = 'MSDAORA')
  16484.             select @datasrctype = @oracle_subscriber
  16485.         else if (upper(@provider_name collate SQL_Latin1_General_CP1_CS_AS) = 'DB2OLEDB')
  16486.             select @datasrctype = @db2universal_subscriber
  16487.     END
  16488.     
  16489.     drop table #subtype
  16490.     drop table #server_info
  16491.  
  16492.     return 0
  16493. GO
  16494. exec dbo.sp_MS_marksystemobject sp_MSget_subtypedatasrc 
  16495. go
  16496. grant exec on dbo.sp_MSget_subtypedatasrc to public
  16497. go
  16498.  
  16499. raiserror('Creating procedure sp_addmergealternatepublisher', 0,1)
  16500. GO
  16501. CREATE PROCEDURE sp_addmergealternatepublisher (
  16502.     @publisher                    sysname,                     /* Publisher server */
  16503.     @publisher_db               sysname,                     /* Publisher database */
  16504.     @publication                sysname,                    /* Publication name */
  16505.     @alternate_publisher        sysname,                    /* Alternate publisher */
  16506.     @alternate_publisher_db     sysname,                    /* Alternate publisher_db */
  16507.     @alternate_publication        sysname,                    /* Alternate publication */
  16508.     @alternate_distributor        sysname,                    /* Alternate publisher's Distributor */
  16509.     @friendly_name                nvarchar(255)    = NULL,        /* Friendly Name for the association */
  16510.     @reserved                   nvarchar(20) = NULL            /* Reserved param for internal use only */
  16511.     ) AS
  16512.  
  16513.     SET NOCOUNT ON
  16514.  
  16515.     /*
  16516.     ** Declarations.
  16517.     */
  16518.     declare @retcode                int
  16519.     declare @pubid                    uniqueidentifier
  16520.     declare @subid                    uniqueidentifier
  16521.     declare @alternate_subid        uniqueidentifier
  16522.     declare    @description            nvarchar(255)
  16523.     declare    @allow_synctoalternate    bit
  16524.     declare @at_publisher            bit
  16525.     declare @subscriber_type        smallint
  16526.  
  16527.     set @at_publisher = 1
  16528.      /*
  16529.     ** Security Check
  16530.     */
  16531.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  16532.     IF @@ERROR <> 0 or @retcode <> 0
  16533.         return (1)
  16534.     
  16535.     /*
  16536.     ** Select the subscription's pubid and subid
  16537.     */
  16538.     select @pubid = pubid, @allow_synctoalternate = allow_synctoalternate from sysmergepublications  
  16539.         where name = @publication and publisher_db = @publisher_db and LOWER(publisher) = LOWER(@publisher)
  16540.     if @pubid is NULL
  16541.         begin
  16542.             raiserror (20026, 11, -1, @publication)
  16543.             return (1)
  16544.         end
  16545.  
  16546.     /* If this is an external call, make the AtPublisher and allows syncto alternate  check */
  16547.     EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  16548.     IF @@ERROR <> 0 or @retcode <>  0
  16549.         set @at_publisher = 0
  16550.         
  16551.     IF LOWER(@reserved collate SQL_Latin1_General_CP1_CS_AS) <> 'internal'
  16552.         begin
  16553.             IF @at_publisher = 0
  16554.                 BEGIN
  16555.                     RAISERROR (21215, 16, -1)
  16556.                     RETURN (1)
  16557.                 END
  16558.             if @allow_synctoalternate = 0
  16559.                 begin
  16560.                     raiserror (21502, 11, -1, @publication)
  16561.                     return (1)
  16562.                 end
  16563.  
  16564.         end
  16565.     select @subid = subid from sysmergesubscriptions  
  16566.         where LOWER(subscriber_server) = LOWER(@publisher) and db_name = @publisher_db and pubid = @pubid
  16567.     /*
  16568.     ** Select the alternate publisher's subid 
  16569.     */
  16570.     select @alternate_subid = subid, @subscriber_type = subscriber_type from sysmergesubscriptions
  16571.         where publication = @alternate_publication
  16572.         and LOWER(subscriber_server) = LOWER(@alternate_publisher) and db_name = @alternate_publisher_db
  16573.     IF @subid is NULL or @alternate_subid IS NULL
  16574.         BEGIN
  16575.             RAISERROR(21216, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16576.             RETURN (1)
  16577.         END
  16578.     IF @subscriber_type  <> 1
  16579.         BEGIN
  16580.             RAISERROR(21216, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16581.             RETURN (1)
  16582.         END
  16583.  
  16584.     IF @friendly_name IS NULL
  16585.         begin
  16586.             select @description = description from sysmergesubscriptions where subid = @alternate_subid
  16587.             if @description IS NULL
  16588.                 begin
  16589.                     select @description = formatmessage(21217, @alternate_publication, @alternate_publisher)
  16590.                 end
  16591.                 
  16592.         end                
  16593.     else
  16594.         select @description = @friendly_name
  16595.  
  16596.  
  16597.     if not exists (select * from MSmerge_altsyncpartners where subid = @subid and alternate_subid = @alternate_subid)
  16598.         begin
  16599.             insert into MSmerge_altsyncpartners(subid, alternate_subid, description)
  16600.                 values(@subid, @alternate_subid, @description)
  16601.             if @@ERROR <> 0
  16602.                 BEGIN
  16603.                     GOTO FAILURE
  16604.                 END
  16605.  
  16606.             update sysmergesubscriptions set distributor = @alternate_distributor where subid = @alternate_subid
  16607.             if @@ERROR <> 0 or @@ROWCOUNT <> 1
  16608.                 BEGIN
  16609.                     GOTO FAILURE
  16610.                 END
  16611.         end                
  16612.     if not exists (select * from MSmerge_altsyncpartners where subid = @alternate_subid and alternate_subid = @subid)
  16613.         begin
  16614.             insert into MSmerge_altsyncpartners(subid, alternate_subid, description)
  16615.                 values(@alternate_subid, @subid, @description)
  16616.             if @@ERROR <> 0
  16617.                 BEGIN
  16618.                     GOTO FAILURE
  16619.                 END
  16620.         end                
  16621.     return (0)
  16622.  
  16623. FAILURE:
  16624.  
  16625.     RAISERROR(21243, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16626.     RETURN (1)
  16627.     
  16628. go
  16629. exec dbo.sp_MS_marksystemobject sp_addmergealternatepublisher 
  16630. go
  16631. grant exec on dbo.sp_addmergealternatepublisher to public
  16632. go
  16633.  
  16634. raiserror('Creating procedure sp_helpmergealternatepublisher', 0,1)
  16635. GO
  16636. CREATE PROCEDURE sp_helpmergealternatepublisher (
  16637.     @publisher                    sysname,                     /* Publisher server */
  16638.     @publisher_db               sysname,                     /* Publisher database */
  16639.     @publication                sysname                     /* Publication name */
  16640.     ) AS
  16641.  
  16642.     SET NOCOUNT ON
  16643.     declare @subid                uniqueidentifier
  16644.     declare @pubid                uniqueidentifier
  16645.     declare @distributor        sysname
  16646.     declare @retcode            int
  16647.     declare @MShelpmergealternatepublisher TABLE
  16648.     (
  16649.         subid                    uniqueidentifier     not null,
  16650.         alternate_publisher     sysname             collate database_default not null,   
  16651.         alternate_publisher_db     sysname             collate database_default not null,   
  16652.         alternate_publication     sysname             collate database_default not null,   
  16653.         alternate_distributor     sysname             collate database_default null,   
  16654.         friendly_name             nvarchar(255)         collate database_default null,   
  16655.         enabled                    bit                 not null
  16656.     )
  16657.     
  16658.     /*
  16659.     ** Select the subscription's pubid and subid
  16660.     */
  16661.     select @pubid = pubid from sysmergepublications  
  16662.                    where name = @publication and
  16663.                        LOWER(publisher) = LOWER(@publisher) and
  16664.                        publisher_db = @publisher_db
  16665.     if @pubid is NULL
  16666.         begin
  16667.             raiserror (20026, 11, -1, @publication)
  16668.             return (1)
  16669.         end
  16670.     select @subid = subid, @distributor = distributor from sysmergesubscriptions  where 
  16671.         LOWER(subscriber_server) = LOWER(@publisher) and db_name = @publisher_db and pubid = @pubid
  16672.     IF @@ERROR <> 0 
  16673.         BEGIN
  16674.             GOTO FAILURE
  16675.         END
  16676.         
  16677.     insert into @MShelpmergealternatepublisher (subid, alternate_publisher, alternate_publisher_db, alternate_publication, alternate_distributor, friendly_name, enabled)
  16678.     select distinct subs.subid,
  16679.         subs.subscriber_server, 
  16680.         subs.db_name, 
  16681.         subs.publication,
  16682.         subs.distributor,
  16683.         subs.description,
  16684.         1 from sysmergesubscriptions subs
  16685.                    where subs.subid in (select alternate_subid from MSmerge_altsyncpartners where subid = @subid)
  16686.     /* select the parent publisher */                       
  16687.     insert into @MShelpmergealternatepublisher (subid, alternate_publisher, alternate_publisher_db, alternate_publication, alternate_distributor, friendly_name, enabled)
  16688.     select distinct  pubs.pubid,
  16689.         pubs.publisher, 
  16690.         pubs.publisher_db, 
  16691.         pubs.name,
  16692.         @distributor,
  16693.         pubs.description,
  16694.         1 from sysmergepublications pubs
  16695.                    where pubs.name = @publication and
  16696.                        LOWER(publisher) = LOWER(@publisher) and
  16697.                        publisher_db = @publisher_db 
  16698.  
  16699.     insert into @MShelpmergealternatepublisher (subid, alternate_publisher, alternate_publisher_db, alternate_publication, alternate_distributor, friendly_name, enabled)
  16700.        select distinct  subs.subid,
  16701.            subs.subscriber_server, 
  16702.         subs.db_name, 
  16703.         subs.publication,
  16704.         subs.distributor,
  16705.         subs.description,
  16706.         0
  16707.         from sysmergesubscriptions subs
  16708.                where subs.subscriber_type = 1 -- only publisher and republishers
  16709.                    and subs.subid = subs.pubid -- only publisher and republishers
  16710.                    and subs.subid not in (select subid from @MShelpmergealternatepublisher)
  16711.         
  16712.     select distinct alternate_publisher,
  16713.         alternate_publisher_db,
  16714.         alternate_publication,
  16715.         alternate_distributor,
  16716.         friendly_name,
  16717.         enabled    
  16718.         from @MShelpmergealternatepublisher 
  16719.     order by alternate_publisher, alternate_publisher_db, alternate_publication, alternate_distributor
  16720.     
  16721.     return (0)
  16722. FAILURE:
  16723.     
  16724.     RETURN (1)
  16725. go
  16726. exec dbo.sp_MS_marksystemobject sp_helpmergealternatepublisher 
  16727. go
  16728. grant exec on dbo.sp_helpmergealternatepublisher to public
  16729. go
  16730.  
  16731.  
  16732. raiserror('Creating procedure sp_dropmergealternatepublisher', 0,1)
  16733. GO
  16734. CREATE PROCEDURE sp_dropmergealternatepublisher (
  16735.     @publisher                    sysname,                     /* Publisher server */
  16736.     @publisher_db               sysname,                     /* Publisher database */
  16737.     @publication                sysname,                    /* Publication name */
  16738.     @alternate_publisher        sysname,                    /* Alternate publisher */
  16739.     @alternate_publisher_db     sysname,                    /* Alternate publisher_db */
  16740.     @alternate_publication        sysname                        /* Alternate publication */
  16741.     ) AS
  16742.  
  16743.     SET NOCOUNT ON
  16744.     declare @retcode                 int
  16745.     declare @subid                    uniqueidentifier
  16746.     declare @alternate_subid        uniqueidentifier
  16747.     
  16748.     /*
  16749.     ** Security Check
  16750.     */
  16751.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  16752.     IF @@ERROR <> 0 or @retcode <> 0
  16753.         return (1)
  16754.  
  16755.     /* Check is there is an invalid attempt to drop the default publiser/publisher_db/publication */
  16756.     if (LOWER(@publisher) = LOWER(@alternate_publisher)) AND
  16757.         (@publisher_db = @alternate_publisher_db) AND
  16758.         (@publication = @alternate_publication)
  16759.         begin
  16760.             RAISERROR(21252, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16761.             return (1)
  16762.         end
  16763.  
  16764.     select @subid = subid from sysmergesubscriptions  
  16765.         where LOWER(subscriber_server) = LOWER(@publisher) and db_name = @publisher_db and publication = @publication
  16766.     /*
  16767.     ** Select the alternate publisher's subid 
  16768.     */
  16769.     select @alternate_subid = subid from sysmergesubscriptions
  16770.         where publication = @alternate_publication
  16771.         and LOWER(subscriber_server) = LOWER(@alternate_publisher) and db_name = @alternate_publisher_db
  16772.     IF @subid is NULL or @alternate_subid IS NULL
  16773.         BEGIN
  16774.             RAISERROR(21216, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16775.             RETURN (1)
  16776.         END
  16777.  
  16778.  
  16779.     if exists (select * from MSmerge_altsyncpartners where subid = @subid and alternate_subid = @alternate_subid)
  16780.         begin
  16781.             delete from MSmerge_altsyncpartners where @subid = subid and alternate_subid = @alternate_subid
  16782.             if @@ERROR <> 0 or @@rowcount <> 1
  16783.                 BEGIN
  16784.                     GOTO FAILURE
  16785.                 END
  16786.         end                
  16787.     return (0)
  16788.  
  16789. FAILURE:
  16790.     RAISERROR(21251, 11, -1,  @alternate_publisher, @alternate_publisher_db, @alternate_publication)
  16791.     RETURN (1)
  16792. go
  16793.  
  16794. exec dbo.sp_MS_marksystemobject sp_dropmergealternatepublisher 
  16795. go
  16796. grant exec on dbo.sp_dropmergealternatepublisher to public
  16797. go
  16798.  
  16799. raiserror(15339,-1,-1,'sp_MScomputemergearticlescreationorder')
  16800. GO
  16801. CREATE PROCEDURE sp_MScomputemergearticlescreationorder
  16802.     @publication sysname
  16803. AS
  16804.     SET NOCOUNT ON
  16805.     DECLARE @pubid uniqueidentifier 
  16806.     DECLARE @max_level int
  16807.     DECLARE @current_level int
  16808.     DECLARE @update_level int
  16809.     DECLARE @limit int
  16810.  
  16811.     SELECT @pubid = NULL
  16812.     -- Get the pubid from sysmergepublications 
  16813.     SELECT @pubid = pubid 
  16814.       FROM sysmergepublications
  16815.      WHERE name = @publication
  16816.        AND UPPER(publisher) = UPPER(@@SERVERNAME)
  16817.        AND publisher_db = DB_NAME()
  16818.  
  16819.     IF @@ERROR <> 0
  16820.         RETURN (1)
  16821.  
  16822.     IF @pubid IS NULL
  16823.     BEGIN
  16824.         RAISERROR(20026, 16, -1, @publication)
  16825.         RETURN (1)
  16826.     END
  16827.  
  16828.     -- Find out the total number of articles in this publication and
  16829.     -- compute the maximum tree height based on the number of articles in 
  16830.     -- the publication. Here, the tree height is counted from the
  16831.     -- leaf-nodes towards the root(s) starting from @max_level
  16832.     SELECT @max_level = COUNT(*) + 10,
  16833.            @limit = 2 * COUNT(*) + 11 
  16834.       FROM sysmergeextendedarticlesview 
  16835.      WHERE pubid = @pubid
  16836.  
  16837.     IF @@ERROR <> 0
  16838.     BEGIN
  16839.         RETURN (1)
  16840.     END
  16841.    
  16842.     -- The following temp table contains the minimal amount of 
  16843.     -- article information that we want to keep around and the current
  16844.     -- computed tree level of the article
  16845.     CREATE TABLE #article_level_info
  16846.     (
  16847.         article         sysname collate database_default not null,
  16848.         source_objid    INT     NOT NULL,
  16849.         tree_level      INT     NOT NULL,
  16850.         nickname        INT     NOT NULL,
  16851.         major_type      TINYINT NOT NULL  -- 1-view&func, 0-other
  16852.     )  
  16853.    
  16854.     CREATE CLUSTERED INDEX ucarticle_level_info 
  16855.         ON #article_level_info(source_objid)
  16856.  
  16857.     IF @@ERROR <> 0
  16858.     BEGIN
  16859.         GOTO Failure
  16860.     END
  16861.  
  16862.     -- Populate the article level info table. All articles will be
  16863.     -- assigned 0 as their initial tree level. Having 
  16864.     -- a tree level of 0 means that the algorithm hasn't discovered 
  16865.     -- any objects that the article depends on within the publication.
  16866.  
  16867.     INSERT INTO #article_level_info 
  16868.     SELECT name, objid, 0, ISNULL(nickname, 5*@max_level),
  16869.         CASE type
  16870.             WHEN 0x40 THEN 1
  16871.             WHEN 0x80 THEN 1
  16872.             ELSE 0
  16873.         END 
  16874.       FROM sysmergeextendedarticlesview
  16875.      WHERE pubid = @pubid
  16876.       
  16877.     -- To jump-start the algorithm, update the tree_level of 
  16878.     -- all articles with no dependency to @max_level.
  16879.  
  16880.     UPDATE #article_level_info 
  16881.        SET tree_level = @max_level
  16882.      WHERE NOT EXISTS (SELECT * 
  16883.                          FROM sysdepends 
  16884.                         WHERE source_objid = id
  16885.                           AND id <> depid)
  16886.     IF @@ERROR <> 0
  16887.         GOTO Failure
  16888.  
  16889.     -- For each increasing tree level starting from @max_level, update the 
  16890.     -- the tree_level of articles depending on objects at the current
  16891.     -- level to current level + 1
  16892.     SELECT @current_level = @max_level
  16893.     WHILE 1 = 1
  16894.     BEGIN
  16895.         SELECT @update_level = @current_level + 1
  16896.  
  16897.         UPDATE #article_level_info
  16898.            SET tree_level = @update_level
  16899.           FROM #article_level_info 
  16900.         INNER JOIN sysdepends d
  16901.             ON #article_level_info.source_objid = d.id 
  16902.         INNER JOIN #article_level_info ali1
  16903.             ON (d.depid = ali1.source_objid       
  16904.                AND ali1.tree_level = @current_level
  16905.                AND d.id <> d.depid)
  16906.     
  16907.         -- Terminate the algorithm if we cannot find any articles 
  16908.         -- depending on articles at the current level     
  16909.         IF @@ROWCOUNT = 0
  16910.             GOTO PHASE1
  16911.  
  16912.         IF @@ERROR <> 0
  16913.             GOTO Failure
  16914.  
  16915.         SELECT @current_level = @current_level + 1
  16916.  
  16917.         -- Although there should not be any circular 
  16918.         -- dependencies among the articles, the following
  16919.         -- check is performed to guarantee that 
  16920.         -- the algorithm will terminate even if there 
  16921.         -- is circular dependency among the articles
  16922.         
  16923.         -- Note that with at least one node per level,
  16924.         -- the current level can never exceed the total 
  16925.         -- number of articles (nodes) unless there is
  16926.         -- circular dependency among the articles.
  16927.         
  16928.         -- @limit is defined to be # of articles + 1
  16929.         -- although @limit = # of articles - 1 will be
  16930.         -- sufficient. This is to make absolutely sure that 
  16931.         -- the algorithm will never terminate too early
  16932.  
  16933.         IF @current_level > @limit
  16934.             GOTO PHASE1
  16935.     END
  16936.  
  16937. PHASE1:
  16938.     
  16939.     -- There may be interdependencies among articles 
  16940.     -- that haven't been included in the previous calculations so
  16941.     -- we compute the proper order among these articles here.
  16942.     SELECT @limit = @max_level - 9
  16943.     SELECT @current_level = 0
  16944.     WHILE 1 = 1
  16945.     BEGIN
  16946.         SELECT @update_level = @current_level + 1
  16947.         
  16948.         UPDATE #article_level_info 
  16949.            SET tree_level = @update_level
  16950.           FROM #article_level_info
  16951.         INNER JOIN sysdepends d
  16952.             ON (#article_level_info.source_objid = d.id
  16953.                 AND #article_level_info.tree_level < @max_level) 
  16954.         INNER JOIN #article_level_info ali1
  16955.             ON (d.depid = ali1.source_objid
  16956.                 AND ali1.tree_level = @current_level
  16957.                 AND d.id <> d.depid)
  16958.         IF @@ROWCOUNT = 0
  16959.             GOTO PHASE2
  16960.         
  16961.         IF @@ERROR <> 0
  16962.             GOTO Failure
  16963.  
  16964.         SELECT @current_level = @current_level + 1
  16965.         IF @current_level > @limit
  16966.             GOTO PHASE2
  16967.     END         
  16968.  
  16969. PHASE2:
  16970.  
  16971.     -- Select the articles out of #article_level_info 
  16972.     -- in ascending order of tree_level. This will give
  16973.     -- the proper order in which articles can be created
  16974.     -- without violating the internal dependencies among
  16975.     -- the themselves. Note that this algorithm still allows 
  16976.     -- unresolved external references outside the publication.
  16977.     -- All this algorithm can guarantee is that all articles will
  16978.     -- be created successfully using the resulting order if 
  16979.     -- there is no dependent object outside the publication. 
  16980.  
  16981.     SELECT article
  16982.       FROM #article_level_info
  16983.     ORDER BY major_type ASC, tree_level ASC, nickname ASC
  16984.  
  16985.     DROP TABLE #article_level_info
  16986.     RETURN (0)
  16987.  
  16988. Failure:
  16989.  
  16990.     DROP TABLE #article_level_info
  16991.     RETURN (1)
  16992. GO
  16993.  
  16994. exec dbo.sp_MS_marksystemobject sp_MScomputemergearticlescreationorder
  16995. go
  16996. grant exec on dbo.sp_MScomputemergearticlescreationorder to public
  16997. go
  16998.  
  16999. raiserror(15339,-1,-1,'sp_MScomputemergeunresolvedrefs')
  17000. GO
  17001. CREATE PROCEDURE sp_MScomputemergeunresolvedrefs
  17002.     @publication sysname, -- Must provide the publication name
  17003.     @article     sysname = '%' -- '%' means all articles in the specified publication, otherwise an exact match is performed
  17004. AS
  17005.     SET NOCOUNT ON 
  17006.     DECLARE @pubid uniqueidentifier 
  17007.     
  17008.     -- Parameter check: @publication
  17009.  
  17010.     IF @publication IS NULL
  17011.     BEGIN
  17012.         RAISERROR (14043, 16, -1, '@publication')
  17013.         RETURN (1)
  17014.     END
  17015.  
  17016.     SELECT @pubid = NULL 
  17017.     -- Get the pubid of the publication
  17018.     SELECT @pubid = pubid 
  17019.       FROM sysmergepublications
  17020.      WHERE name = @publication
  17021.        AND UPPER(publisher) = UPPER(@@SERVERNAME)
  17022.        AND publisher_db = DB_NAME()
  17023.     
  17024.     IF @pubid IS NULL
  17025.     BEGIN
  17026.         RAISERROR (20026, 11, -1, @publication)
  17027.         RETURN (1)    
  17028.     END
  17029.  
  17030.     SELECT DISTINCT 
  17031.            'article' = a.name, 
  17032.            'dependent object' = o.name, 
  17033.            'dependent object owner' = u.name, 
  17034.            'dependent objectid' = o.id 
  17035.       FROM dbo.sysmergeextendedarticlesview a
  17036.     INNER JOIN sysdepends dep
  17037.         ON a.objid = dep.id
  17038.        AND a.pubid = @pubid
  17039.        AND (@article = '%' OR name = @article)
  17040.        AND dep.depid NOT IN (SELECT objid FROM dbo.sysmergeextendedarticlesview
  17041.                               WHERE pubid = @pubid 
  17042.                                 AND (@article = '%' OR name = @article))
  17043.     INNER JOIN sysobjects o
  17044.         ON dep.depid = o.id
  17045.     INNER JOIN sysusers u
  17046.         ON u.uid = o.uid          
  17047. GO
  17048.  
  17049. exec dbo.sp_MS_marksystemobject sp_MScomputemergeunresolvedrefs
  17050. go
  17051. grant exec on dbo.sp_MScomputemergeunresolvedrefs to public
  17052. go
  17053.  
  17054. raiserror('Creating procedure sp_MSCheckmergereplication', 0,1)
  17055. GO
  17056.  
  17057. CREATE PROCEDURE sp_MSCheckmergereplication
  17058. AS
  17059.     SET NOCOUNT ON
  17060.     declare @category int
  17061.     declare @db_name sysname
  17062.  
  17063.     select @db_name=db_name()
  17064.     select @category=category FROM master..sysdatabases WHERE name = @db_name collate database_default
  17065.     if @category & 4 = 0
  17066.         begin
  17067.             raiserror(21147, 16, -1, @db_name)
  17068.             return (1)
  17069.         end
  17070.     return (0)    
  17071. go
  17072. exec dbo.sp_MS_marksystemobject sp_MSCheckmergereplication
  17073. go
  17074.  
  17075. grant execute on dbo.sp_MSCheckmergereplication to public
  17076. go
  17077.  
  17078. raiserror('Creating procedure sp_MSgetpubinfo', 0,1)
  17079. GO
  17080.  
  17081. CREATE PROCEDURE sp_MSgetpubinfo (
  17082.     @publication    sysname,    /* The publication name */
  17083.     @publisher        sysname,
  17084.     @pubdb            sysname
  17085.     ) AS
  17086.  
  17087.     SET NOCOUNT ON
  17088.  
  17089.     select pubid from sysmergepublications where name = @publication and
  17090.             LOWER(publisher) = LOWER(@publisher) and LOWER(publisher_db) = LOWER(@pubdb)
  17091.             
  17092. go
  17093. exec dbo.sp_MS_marksystemobject sp_MSgetpubinfo
  17094. go
  17095.  
  17096. grant execute on dbo.sp_MSgetpubinfo to public
  17097. go
  17098.  
  17099. raiserror('Creating procedure sp_MSaddmergedynamicsnapshotjob', 0,1)
  17100. go
  17101. --
  17102. -- Name: sp_MSaddmergedynamicsnapshotjob
  17103. --
  17104. -- Description: This procedure sets up a SQL Server Agent job for dynamic 
  17105. --              snapshot generation and associates a row in 
  17106. --              MSdynamicsnapshotjobs for the job to the specified publication.
  17107. --
  17108. -- Notes: 1) If a local path is specified for the @dynamic_snapshot_location,
  17109. --           the local path of the Distribution server will be used. 
  17110. --        2) This procedure will not check whether the given path is already in
  17111. --           use by another dynamic snapshot generation job. Sharing the same
  17112. --           dynamic snapshot location among different dynamic snapshot 
  17113. --           generation jobs can lead to file corruption and/or snapshot files 
  17114. --           being overwritten.  
  17115. --        3) A regular snapshot job must be added for the publication before
  17116. --           a dynamic snapshot generation job can be scheduled.
  17117. --        4) This procedure will not check for the existence of the given
  17118. --           dynamic snapshot location.
  17119. --        5) The specified publication must be enabled for dynamic filtering.
  17120. --        6) If @dynamic_snapshot_jobname is specified, it must be unique 
  17121. --           among all the jobs at the distributor's msdb. If it is left
  17122. --           unspecified, a job name will be generated according to the
  17123. --           following rule:
  17124. --           'dyn_' + (job name for the regular snapshot job) + (guid string)
  17125. --           Note that (job name for the regular snapshot job) can be truncated
  17126. --           if the resulting name is too long.
  17127. -- 
  17128. -- Parameters: @publication sysname (mandatory)
  17129. --             @dynamic_filter_login sysname (optional, default null)
  17130. --             @dynamic_filter_hostname sysname (optional, default null)
  17131. --             @dynamic_snapshot_location nvarchar(255) (mandatory)
  17132. --             @dynamic_snapshot_jobid (optional, output, default null)
  17133. --             @dynamic_snapshot_jobname (optional, output, default null)
  17134. --             Scheduling information:
  17135. --             @frequency_type int (optional, default 4 == Daily)
  17136. --             @frequency_interval int (optional, default 1 == Every day)
  17137. --             @frequency_subday int (optional, default 4 (Sub interval = Minute))
  17138. --             @frequency_subday_interval int (optional, default 5 == Every five minutes)
  17139. --             @frequency_relative_interval int (optional, default 1) 
  17140. --             @frequency_recurrence_factor int (optional, default 0) 
  17141. --             @active_start_date int (optional, default 0 == Today)
  17142. --             @active_end_date int (optional, default 99991231) 
  17143. --             @active_start_time_of_day int (optional, default 0 == Now)
  17144. --             @active_end_time_of_day int (optional, default 235959)
  17145. --
  17146. -- Returns: 0 - succeeded
  17147. --          1 - failed
  17148. --
  17149. -- Result set (upon successful completion of the operation):
  17150. --          dynamic_snapshot_jobname sysname
  17151. --          dynamic_snapshot_jobid uniqueidentifier
  17152. -- Security: Only members of the 'sysadmin' server role and members of the
  17153. --           'db_owner' database role can invoke this procedure successfully.
  17154. --           Security check is performed inside the procedure.
  17155. --
  17156. create procedure sp_MSaddmergedynamicsnapshotjob (
  17157.     @publication sysname,
  17158.     @dynamic_filter_login sysname = null,
  17159.     @dynamic_filter_hostname sysname = null,
  17160.     @dynamic_snapshot_location nvarchar(255), 
  17161.     @dynamic_snapshot_jobname sysname = null output,
  17162.     @dynamic_snapshot_jobid uniqueidentifier = null output,
  17163.  
  17164.     -- Scheduling information
  17165.     @frequency_type              int = 4,
  17166.     @frequency_interval          int = 1,
  17167.     @frequency_subday            int = 4,
  17168.     @frequency_subday_interval   int = 5,
  17169.     @frequency_relative_interval int = 1, 
  17170.     @frequency_recurrence_factor int = 0,
  17171.     @active_start_date           int = 0,
  17172.     @active_end_date             int = 99991231,
  17173.     @active_start_time_of_day    int = 0, 
  17174.     @active_end_time_of_day      int = 235959
  17175.     )
  17176. as
  17177. begin
  17178.     set nocount on
  17179.  
  17180.     declare @retcode int
  17181.     declare @pubid uniqueidentifier
  17182.     declare @dynamic_filters bit
  17183.     declare @snapshot_jobid uniqueidentifier 
  17184.     declare @command_line nvarchar(4000)
  17185.     declare @distribdb sysname
  17186.     declare @rpcsrvname sysname
  17187.     declare @distributor sysname
  17188.     declare @fjobcreated bit
  17189.     declare @distproc nvarchar(4000)
  17190.     declare @id int 
  17191.  
  17192.     -- Initializations
  17193.     select @retcode = 0
  17194.     select @pubid = null
  17195.     select @dynamic_filters = 0
  17196.     select @snapshot_jobid = null
  17197.     select @fjobcreated = 0
  17198.  
  17199.     if not exists (select * from sysobjects where name = 'sysmergepublications')
  17200.     begin
  17201.         raiserror (20054, 16, -1)
  17202.         return (1)
  17203.     end
  17204.  
  17205.     -- Make sure that caller is a member of 'sysadmins' or 'db_owner'
  17206.     exec @retcode = dbo.sp_MSreplcheck_publish
  17207.     if @@error <> 0 or @retcode <> 0
  17208.         return (1)
  17209.     
  17210.     -- Check that the given dynammic filter login is in the PAL
  17211.     exec @retcode = sp_check_publication_access
  17212.         @publication = @publication,
  17213.         @given_login = @dynamic_filter_login
  17214.     if @retcode <> 0 or @@error <> 0
  17215.         return 1
  17216.  
  17217.     select @dynamic_snapshot_location = ltrim(@dynamic_snapshot_location)
  17218.     -- Specified @dynamic_snapshot_location must be non-empty
  17219.     if @dynamic_snapshot_location is null or 
  17220.        @dynamic_snapshot_location = N''
  17221.     begin
  17222.         raiserror(21321, 16, -1)         
  17223.         return (1)
  17224.     end
  17225.  
  17226.     -- Verify that the given publication exists and get the pubid at the
  17227.     -- same time
  17228.     select @pubid = pubid,
  17229.            @dynamic_filters = dynamic_filters
  17230.       from dbo.sysmergepublications
  17231.      where upper(publisher) = upper(@@servername)
  17232.        and publisher_db = db_name()
  17233.        and name = @publication
  17234.  
  17235.     if @pubid is null
  17236.     begin
  17237.         raiserror(20026, 16, -1, @publication) 
  17238.         return (1)        
  17239.     end
  17240.  
  17241.     -- The given publication must be enabled for dynamic filtering
  17242.     if @dynamic_filters <> 1
  17243.     begin
  17244.         raiserror(21323, 16, -1)
  17245.         return (1)
  17246.     end
  17247.  
  17248.     -- A regular snapshot job is required before a dynamic snapshot job
  17249.     -- can be scheduled
  17250.     select @snapshot_jobid = snapshot_jobid from MSmerge_replinfo
  17251.      where repid = @pubid
  17252.  
  17253.     if @snapshot_jobid is null
  17254.     begin
  17255.         raiserror(21324, 16, -1)            
  17256.         return (1)
  17257.     end
  17258.  
  17259.     -- The given dynamic snapshot job name cannot be '%' and it cannot match
  17260.     -- any of the existing dynamic snapshot job name
  17261.     if @dynamic_snapshot_jobname = '%'
  17262.     begin
  17263.         raiserror(21327, 16, -1)
  17264.         return (1)
  17265.     end
  17266.  
  17267.     if exists (select * 
  17268.                  from MSdynamicsnapshotjobs 
  17269.                 where name = @dynamic_snapshot_jobname)
  17270.     begin
  17271.         raiserror(21328, 16, -1, @dynamic_snapshot_jobname)
  17272.         return (1)
  17273.     end    
  17274.  
  17275.  
  17276.     -- Get distributor information for RPC
  17277.     exec @retcode = sp_helpdistributor @distributor = @distributor output,
  17278.                                        @distribdb = @distribdb output,
  17279.                                        @rpcsrvname = @rpcsrvname output
  17280.     if @@error <> 0 or @retcode <> 0
  17281.         return (1)
  17282.  
  17283.     select @distproc = rtrim(@rpcsrvname) + N'.' + @distribdb + N'.' + N'dbo.sp_MSadddynamicsnapshotjobatdistributor'
  17284.  
  17285.     exec @retcode = @distproc 
  17286.         @regular_snapshot_jobid = @snapshot_jobid,
  17287.         @dynamic_filter_login = @dynamic_filter_login,
  17288.         @dynamic_filter_hostname = @dynamic_filter_hostname,
  17289.         @dynamic_snapshot_location = @dynamic_snapshot_location,
  17290.         @dynamic_snapshot_jobname = @dynamic_snapshot_jobname output,
  17291.         @dynamic_snapshot_jobid = @dynamic_snapshot_jobid output,
  17292.         @freqtype = @frequency_type,
  17293.         @freqinterval = @frequency_interval,
  17294.         @freqsubtype = @frequency_subday,
  17295.         @freqsubinterval = @frequency_subday_interval,
  17296.         @freqrelativeinterval = @frequency_relative_interval,
  17297.         @freqrecurrencefactor = @frequency_recurrence_factor,
  17298.         @activestartdate = @active_start_date,
  17299.         @activeenddate = @active_end_date,
  17300.         @activestarttimeofday = @active_start_time_of_day,
  17301.         @activeendtimeofday = @active_end_time_of_day
  17302.     
  17303.     if @retcode <> 0 or @@error <> 0
  17304.         goto Failure
  17305.  
  17306.     select @fjobcreated = 1
  17307.  
  17308.     insert MSdynamicsnapshotjobs 
  17309.     (name, pubid, job_id, dynamic_filter_login, dynamic_filter_hostname, 
  17310.      dynamic_snapshot_location)
  17311.     values
  17312.     (@dynamic_snapshot_jobname, @pubid, @dynamic_snapshot_jobid, 
  17313.      @dynamic_filter_login, @dynamic_filter_hostname, 
  17314.      @dynamic_snapshot_location)    
  17315.     
  17316.     if @@error <> 0
  17317.     begin
  17318.         goto Failure
  17319.     end
  17320.  
  17321.     select @id = @@identity    
  17322.  
  17323.     select 'id'                       = @id,
  17324.            'dynamic_snapshot_jobname' = @dynamic_snapshot_jobname,
  17325.            'dynamic_snapshot_jobid' = @dynamic_snapshot_jobid
  17326.     return 0
  17327.  
  17328. Failure:
  17329.     if @fjobcreated = 1
  17330.     begin
  17331.         select @distproc = rtrim(@rpcsrvname) + N'.' + @distribdb + N'.' + N'dbo.sp_MSdeleterepljob'
  17332.         exec @distproc @job_id = @dynamic_snapshot_jobid
  17333.     end
  17334.     return @retcode
  17335. end
  17336. go
  17337. exec dbo.sp_MS_marksystemobject sp_MSaddmergedynamicsnapshotjob
  17338. go
  17339.  
  17340. grant execute on dbo.sp_MSaddmergedynamicsnapshotjob to public
  17341. go
  17342.  
  17343.  
  17344. raiserror('Creating procedure sp_MSdropmergedynamicsnapshotjob', 0,1)
  17345. go
  17346. --
  17347. -- Name: sp_MSdropmergedynamicsnapshotjob
  17348. --
  17349. -- Description: This procedure drops a scheduled dynamic snapshot job for
  17350. --              a publication and the associated meta-data in 
  17351. --              MSdynamicsnapshotjobs. This procedure will also remove all 
  17352. --              files in the associated dynamic snapshot location.
  17353. --
  17354. -- Parameters: @publication sysname (mandatory)
  17355. --             @dynamic_snapshot_jobname (optional, default '%')
  17356. --             @dynamic_snapshot_jobid uniqueidentifier (optional, default 
  17357. --             null) When @dynamic_snapshot_jobid is null and 
  17358. --             @dynamic_snapshot_jobname is '%', all dynamic snapshot
  17359. --             jobs for the specified publication will be dropped.
  17360. --             @ignore_distributor bit (optional, default 0) 
  17361. --
  17362. -- Notes: 1) At most one of @dynamic_snapshot_jobid and 
  17363. --           @dynamic_snapshot_jobname can be specified with a non-default 
  17364. --           value.
  17365. --           
  17366. -- Returns: 0 - succeeded
  17367. --          1 - failed
  17368. --
  17369. -- Security: Only members of the 'sysadmin' server role and the 'db_owner'  
  17370. -- database role can execute this procedure successfully even though execute
  17371. -- permission of this procedure is granted to public.
  17372. --
  17373. create procedure sp_MSdropmergedynamicsnapshotjob (
  17374.     @publication sysname,
  17375.     @dynamic_snapshot_jobname sysname = '%',
  17376.     @dynamic_snapshot_jobid uniqueidentifier = null,
  17377.     @ignore_distributor bit = 0
  17378.     )
  17379. as
  17380. begin
  17381.     set nocount on
  17382.     
  17383.     declare @retcode int
  17384.     declare @pubid uniqueidentifier
  17385.     declare @dynamic_snapshot_location nvarchar(255)
  17386.     declare @guidstr nvarchar(40)
  17387.     declare @dynamic_snapshot_jobid_from_cursor uniqueidentifier
  17388.  
  17389.     declare @distributor sysname
  17390.     declare @distribdb sysname
  17391.     declare @rpcsrvname sysname
  17392.     declare @distproc nvarchar(4000)
  17393.  
  17394.     select @retcode = 0
  17395.     select @pubid = null
  17396.     select @dynamic_snapshot_location = null
  17397.  
  17398.  
  17399.     if not exists (select * from sysobjects where name = 'sysmergepublications')
  17400.     begin
  17401.         raiserror (20054, 16, -1)
  17402.         return (1)
  17403.     end
  17404.  
  17405.     -- Make sure that caller is a member of 'sysadmins' or 'db_owner'
  17406.     exec @retcode = dbo.sp_MSreplcheck_publish
  17407.     if @@error <> 0 or @retcode <> 0
  17408.         return (1)
  17409.  
  17410.     select @pubid = pubid 
  17411.       from dbo.sysmergepublications 
  17412.      where name = @publication
  17413.        and upper(publisher) = upper(@@servername)
  17414.        and publisher_db = db_name()
  17415.   
  17416.     if @pubid is null
  17417.     begin
  17418.         raiserror(20026, 16, -1, @publication)
  17419.         return (1)
  17420.     end
  17421.     
  17422.     -- At most one of @dynamic_snapshot_jobid and @dynamic_snapshot_jobname
  17423.     -- can be specified with a non-default value
  17424.     if @dynamic_snapshot_jobid is not null and
  17425.        @dynamic_snapshot_jobname <> N'%'
  17426.     begin
  17427.         raiserror(21329, 16, -1)
  17428.         return (1)
  17429.     end
  17430.  
  17431.     if @dynamic_snapshot_jobid is null and @dynamic_snapshot_jobname = N'%'
  17432.     begin
  17433.  
  17434.         declare hJobsCursor cursor local fast_forward for
  17435.             select job_id 
  17436.               from MSdynamicsnapshotjobs 
  17437.              where pubid = @pubid
  17438.         if @@error <> 0
  17439.             return 1
  17440.  
  17441.         open hJobsCursor 
  17442.         if @@error <> 0
  17443.             return 1
  17444.             
  17445.  
  17446.         fetch hJobsCursor into @dynamic_snapshot_jobid_from_cursor 
  17447.           
  17448.         begin transaction
  17449.         save transaction sp_MSdropdynamicsnapshotjobC
  17450.             
  17451.         while (@@fetch_status <> -1)
  17452.         begin
  17453.             if @dynamic_snapshot_jobid_from_cursor is not null
  17454.             begin
  17455.                 exec @retcode = sp_MSdropmergedynamicsnapshotjob 
  17456.                     @publication = @publication,
  17457.                     @dynamic_snapshot_jobid = @dynamic_snapshot_jobid_from_cursor,
  17458.                     @ignore_distributor = @ignore_distributor
  17459.                 if @@error <> 0 or @retcode <> 0
  17460.                     goto CursorFailure
  17461.             end
  17462.             fetch hJobsCursor into @dynamic_snapshot_jobid_from_cursor
  17463.         end                
  17464.  
  17465.         commit transaction
  17466.         close hJobsCursor
  17467.         deallocate hJobsCursor        
  17468.         return 0
  17469. CursorFailure:
  17470.  
  17471.  
  17472.         rollback transaction sp_MSdropdynamicsnapshotjobC
  17473.         commit transaction
  17474.         close hJobsCursor
  17475.         deallocate hJobsCursor
  17476.         return 1
  17477.     end
  17478.  
  17479.     select @pubid = pubid 
  17480.       from dbo.sysmergepublications 
  17481.      where name = @publication
  17482.        and upper(publisher) = upper(@@servername)
  17483.        and publisher_db = db_name()
  17484.  
  17485.     if @dynamic_snapshot_jobid is null
  17486.     begin   
  17487.         select @dynamic_snapshot_location = dynamic_snapshot_location,
  17488.                @dynamic_snapshot_jobid = job_id
  17489.           from dbo.MSdynamicsnapshotjobs
  17490.          where pubid = @pubid
  17491.            and name = @dynamic_snapshot_jobname 
  17492.     end
  17493.     else 
  17494.     begin
  17495.         select @dynamic_snapshot_location = dynamic_snapshot_location 
  17496.           from dbo.MSdynamicsnapshotjobs
  17497.          where pubid = @pubid
  17498.            and job_id = @dynamic_snapshot_jobid 
  17499.     end
  17500.  
  17501.     if @dynamic_snapshot_location is null
  17502.     begin
  17503.         if @dynamic_snapshot_jobid is null
  17504.         begin
  17505.             raiserror(21326, 16, -1, N'@dynamic_snapshot_jobname', @dynamic_snapshot_jobname)
  17506.         end
  17507.         else
  17508.         begin
  17509.             select @guidstr = coalesce(convert(nvarchar(40), @dynamic_snapshot_jobid) collate database_default, '(NULL)' collate database_default)
  17510.             raiserror(21326, 16, -1, N'@dynamic_snapshot_jobid', @guidstr)
  17511.         end
  17512.         return (1)        
  17513.     end
  17514.  
  17515.     -- Get distributor info for RPC
  17516.     if @ignore_distributor = 0
  17517.     begin
  17518.         exec @retcode = sp_helpdistributor @distributor = @distributor output,
  17519.                                            @distribdb = @distribdb output,
  17520.                                            @rpcsrvname = @rpcsrvname output
  17521.     
  17522.         select @rpcsrvname = rtrim(@rpcsrvname)
  17523.     
  17524.         select @distproc = @rpcsrvname + N'.' + @distribdb + N'.' + N'dbo.sp_MSdeletefoldercontents'
  17525.         -- Try to delete the files 
  17526.         exec @retcode = @distproc @dynamic_snapshot_location
  17527.         -- Ignore errors 
  17528.     end    
  17529.     select @retcode = 0
  17530.  
  17531.     begin transaction 
  17532.     save transaction sp_MSdropmergedynamicsnapshotjob
  17533.  
  17534.     -- Delete row from MSdynamicsnapshotjobs
  17535.     delete dbo.MSdynamicsnapshotjobs 
  17536.      where pubid = @pubid
  17537.        and job_id = @dynamic_snapshot_jobid
  17538.  
  17539.     if @@error <> 0
  17540.         goto Failure
  17541.  
  17542.     if @ignore_distributor = 0
  17543.     begin
  17544.         -- Drop the dynamic snapshot job at the distributor 
  17545.         select @distproc = @rpcsrvname + N'.' + @distribdb + N'.' + N'dbo.sp_MSdeleterepljob'
  17546.  
  17547.         exec @retcode = @distproc @dynamic_snapshot_jobid
  17548.         if @retcode <> 0 or @@error <> 0
  17549.             goto Failure
  17550.     end
  17551.     commit transaction
  17552.     return 0
  17553.  
  17554. Failure:
  17555.     rollback transaction sp_MSdropmergedynamicsnapshotjob
  17556.     commit transaction
  17557.     return 1
  17558. end
  17559. go
  17560.  
  17561. exec dbo.sp_MS_marksystemobject sp_MSdropmergedynamicsnapshotjob
  17562.  
  17563. grant execute on sp_MSdropmergedynamicsnapshotjob to public
  17564. go
  17565.  
  17566. raiserror('Creating procedure sp_MShelpmergedynamicsnapshotjob', 0, 1)
  17567. go
  17568. --
  17569. -- Name: sp_MShelpmergedynamicsnapshotjob
  17570. --
  17571. -- Description: This procedure returns a listing of dynamic snapshot jobs.
  17572. --              
  17573. -- Parameters: @publication sysname (optional, default '%'): When @publication
  17574. --             is '%', all dynamic snapshot jobs with the matching 
  17575. --             @dynamic_snapshot_jobid and @dynamic_snapshot_jobname will be 
  17576. --             returned.
  17577. --             @dynamic_snapshot_jobname sysname (optional, default '%'): When 
  17578. --             @dynamic_snapshot_jobname is '%', all dynamic snapshot jobs that
  17579. --             belong to @publication with the matching @dynamic_snapshot_jobid
  17580. --             will be returned.  
  17581. --             @dynamic_snapshot_jobid (optional, default null): When 
  17582. --             @dynamic_snapshot_jobid is null, all dynamic snapshot jobs 
  17583. --             that belong to @publication with the matching 
  17584. --             @dynamic_snapshot_jobname will be returned.
  17585. --
  17586. -- Notes: If all parameters are left unspecified when this procedure is called,
  17587. --        all dynamic snapshot jobs for the current database will be returned.
  17588. --
  17589. -- Result: id int
  17590. --         job_name sysname 
  17591. --         job_id uniqueidentifier -- job id of the dynamic snapshot job
  17592. --         dynamic_filter_login sysname 
  17593. --         dynamic_filter_hostname sysname
  17594. --         dynamic_snapshot_location nvarchar(255) 
  17595. -- Returns: 0 - succeeded
  17596. --          1 - failed
  17597. --
  17598. -- Security: Execute permission of this stored procedure is granted to public
  17599. --
  17600. create procedure sp_MShelpmergedynamicsnapshotjob (
  17601.     @publication sysname = N'%',
  17602.     @dynamic_snapshot_jobname sysname = N'%',
  17603.     @dynamic_snapshot_jobid uniqueidentifier = null
  17604.     )
  17605. as
  17606. begin
  17607.     set nocount on
  17608.  
  17609.     if not exists (select * from sysobjects where name = 'sysmergepublications')
  17610.     begin
  17611.         return 0
  17612.     end
  17613.  
  17614.     select 'id' = j.id,
  17615.            'job_name' = j.name,
  17616.            'job_id' = j.job_id, 
  17617.            'dynamic_filter_login' = j.dynamic_filter_login,
  17618.            'dynamic_filter_hostname' = j.dynamic_filter_hostname,
  17619.            'dynamic_snapshot_location' = j.dynamic_snapshot_location
  17620.       from sysmergepublications p
  17621.      inner join MSdynamicsnapshotjobs j
  17622.         on p.pubid = j.pubid
  17623.      where (p.name = @publication or @publication = N'%')
  17624.        and (j.name = @dynamic_snapshot_jobname or @dynamic_snapshot_jobname = N'%')
  17625.        and (j.job_id = @dynamic_snapshot_jobid or @dynamic_snapshot_jobid is null) 
  17626.  
  17627.     if @@error <> 0
  17628.         return (1)
  17629.     else
  17630.         return (0)
  17631.  
  17632. end
  17633. go
  17634. exec dbo.sp_MS_marksystemobject sp_MShelpmergedynamicsnapshotjob
  17635. go
  17636. grant execute on dbo.sp_MShelpmergedynamicsnapshotjob to public
  17637. go
  17638. create procedure sp_MSremove_userscript(
  17639. @pubid                uniqueidentifier,
  17640. @drop_publication    bit = 0
  17641. )as
  17642.     declare @retention            int
  17643.     declare @last_snapshot        datetime
  17644.     declare @post_snapshot_ver    int
  17645.     declare @post_snapshot_type    int
  17646.     declare @user_script_type    int
  17647.     declare @retcode            int
  17648.     declare @len                int
  17649.  
  17650.     declare @file_path            nvarchar(4000)
  17651.     declare @delfile_cmd        nvarchar(4000)
  17652.     declare @rmdir_cmd            nvarchar(4000)
  17653.     
  17654.     select @post_snapshot_type=52
  17655.     select @user_script_type=46
  17656.     
  17657.     if not exists (select * from sysmergeschemachange where pubid=@pubid and schematype=@user_script_type)
  17658.         return (0)
  17659.     select @retention=retention from sysmergepublications where pubid=@pubid
  17660.     select @last_snapshot=last_validated from sysmergesubscriptions where pubid=@pubid and subid=@pubid
  17661.  
  17662.     --I do not want to remove  script files by setting retention to 0
  17663.     if (@retention=0 or dateadd(day, -@retention, getdate()) < @last_snapshot) and @drop_publication = 0
  17664.         return (0)
  17665.  
  17666.     select @post_snapshot_ver=schemaversion from sysmergeschemachange 
  17667.         where schematype=@post_snapshot_type and pubid=@pubid
  17668.         
  17669.     --only get those script that can be safely removed
  17670.     
  17671.     declare #per_script cursor local fast_forward for
  17672.         select schematext from sysmergeschemachange 
  17673.             where pubid=@pubid and schematype=@user_script_type 
  17674.             and (schemaversion<@post_snapshot_ver or @drop_publication = 1)
  17675.     open #per_script
  17676.     fetch #per_script into @file_path
  17677.     while (@@fetch_status<>-1)
  17678.     begin
  17679.     if(left(@file_path, 1) = N'0' or left(@file_path, 1) = N'1')
  17680.         select @file_path = right(@file_path, len(@file_path) - 1)
  17681.         select @delfile_cmd = N'del "' + @file_path + N'"'
  17682.         EXEC @retcode = master..xp_cmdshell @delfile_cmd, NO_OUTPUT
  17683.         if @@ERROR<>0
  17684.             goto FAILURE
  17685.         select @len=CHARINDEX ( '\' , reverse(@file_path) ) 
  17686.         select @file_path=SUBSTRING(@file_path , 1 , len(@file_path)-@len + 1)
  17687.         
  17688.         select @delfile_cmd = N'rmdir "' + @file_path + N'"'
  17689.         EXEC @retcode = master..xp_cmdshell @delfile_cmd, NO_OUTPUT
  17690.         if @@ERROR<>0
  17691.             goto FAILURE
  17692.         fetch next from #per_script into @file_path
  17693.     end
  17694.     
  17695.     close #per_script
  17696.     deallocate #per_script
  17697.     return (0)
  17698. FAILURE:
  17699.     close #per_script
  17700.     deallocate #per_script
  17701.     return (1)
  17702. go
  17703. EXEC dbo.sp_MS_marksystemobject 'sp_MSremove_userscript'
  17704. go
  17705. grant execute on sp_MSremove_userscript to public
  17706. go
  17707. dump tran master with no_log
  17708. go
  17709.  
  17710.  
  17711.  
  17712.  
  17713. checkpoint
  17714. go
  17715.  
  17716.  
  17717.  
  17718. use master
  17719. go
  17720.  
  17721. execute dbo.sp_configure 'update',1
  17722. go
  17723. reconfigure with override
  17724. go
  17725.  
  17726. set ANSI_NULLS off
  17727. go
  17728.  
  17729. dump tran master with no_log
  17730. go
  17731.  
  17732. /* 
  17733. ** Drop the stored procedures in this script using the old dropping SP 
  17734. ** and then drop itself
  17735. */
  17736. if exists (select * from sysobjects
  17737.     where type = 'P '
  17738.             and name = 'sp_MSdrop_rlrecon')
  17739. begin
  17740.     drop procedure sp_MSdrop_rlrecon
  17741. end
  17742.  
  17743. /*
  17744. ** Create stored procedures to drop the stored procedures
  17745. ** created by this script
  17746. */
  17747.  
  17748. raiserror('Creating procedure sp_MSdrop_rlrecon', 0,1)
  17749. GO
  17750. create procedure sp_MSdrop_rlrecon
  17751. as
  17752.  
  17753.     if exists (select * from sysobjects
  17754.     where type = 'P'
  17755.         and name = 'sp_MSaddinitialpublication')
  17756.     drop procedure sp_MSaddinitialpublication
  17757.  
  17758.     if exists (select * from sysobjects
  17759.     where type = 'P'
  17760.         and name = 'sp_MSaddinitialsubscription')
  17761.     drop procedure sp_MSaddinitialsubscription
  17762.  
  17763.     if exists (select * from sysobjects
  17764.         where type = 'P'
  17765.             and name = 'sp_MSdropconstraints')
  17766.     drop procedure sp_MSdropconstraints
  17767.  
  17768.     if exists (select * from sysobjects
  17769.             where type = 'P'
  17770.                 and name = 'sp_MSexclause')
  17771.         drop procedure sp_MSexclause
  17772.  
  17773.  
  17774.     if exists (select * from sysobjects
  17775.             where type = 'P'
  17776.                 and name = 'sp_MSgetcolordinalfromcolname')
  17777.         drop procedure sp_MSgetcolordinalfromcolname
  17778.         
  17779.     if exists (select * from sysobjects
  17780.             where type = 'P'
  17781.                 and name = 'sp_MSinsertbeforeimageclause')
  17782.         drop procedure sp_MSinsertbeforeimageclause
  17783.  
  17784.     if exists (select * from sysobjects
  17785.             where type = 'P'
  17786.                 and name = 'sp_MSmakectsview')
  17787.         drop procedure sp_MSmakectsview
  17788.  
  17789.     if exists (select * from sysobjects
  17790.                 where type = 'P' and
  17791.                 name = 'sp_MSmakeinsertproc')
  17792.         drop procedure sp_MSmakeinsertproc
  17793.         
  17794.     if exists (select * from sysobjects
  17795.                 where type = 'P' and
  17796.                 name = 'sp_MSmakeupdateproc')
  17797.         drop procedure sp_MSmakeupdateproc 
  17798.         
  17799.     if exists (select * from sysobjects
  17800.                 where type = 'P' and
  17801.                 name = 'sp_MSmakeselectproc')
  17802.         drop procedure sp_MSmakeselectproc 
  17803.  
  17804.     if exists (select * from sysobjects
  17805.                 where type = 'P' and
  17806.                 name = 'sp_MSreplcheck_permission')
  17807.         drop procedure sp_MSreplcheck_permission 
  17808.  
  17809.     if exists (select * from sysobjects
  17810.     where type = 'P '
  17811.             and name = 'sp_MSinsertschemachange')
  17812.     drop procedure sp_MSinsertschemachange
  17813.  
  17814.     if exists (select * from sysobjects
  17815.     where type = 'P'
  17816.         and name = 'sp_MSaddinitialarticle')
  17817.     drop procedure sp_MSaddinitialarticle
  17818.  
  17819.     if exists (select * from sysobjects
  17820.     where type = 'P'
  17821.         and name = 'sp_MSaddinitialschemaarticle')
  17822.     drop procedure sp_MSaddinitialschemaarticle
  17823.         
  17824.     if exists (select * from sysobjects
  17825.                 where type = 'P' and
  17826.                 name = 'sp_MSinitdynamicsubscriber')
  17827.         drop procedure sp_MSinitdynamicsubscriber 
  17828.         
  17829.     if exists (select * from sysobjects
  17830.                 where type = 'P' and
  17831.                 name = 'sp_MSmakearticleprocs')
  17832.         drop procedure sp_MSmakearticleprocs
  17833.  
  17834.     if exists (select * from sysobjects
  17835.                 where type = 'P' and
  17836.                 name = 'sp_MSchecksnapshotstatus')
  17837.         drop procedure sp_MSchecksnapshotstatus
  17838.  
  17839.     if exists (select * from sysobjects
  17840.         where type = 'P'
  17841.             and name = 'sp_MSupdatesysmergearticles')
  17842.         drop procedure sp_MSupdatesysmergearticles        
  17843.  
  17844.     if exists (select * from sysobjects
  17845.         where type = 'P'
  17846.             and name = 'sp_MSdroparticletombstones')
  17847.         drop procedure sp_MSdroparticletombstones        
  17848.  
  17849.     if exists (select * from sysobjects
  17850.         where type = 'P'
  17851.             and name = 'sp_MSproxiedmetadata')
  17852.         drop procedure sp_MSproxiedmetadata        
  17853.     
  17854.     if exists (select * from sysobjects
  17855.                 where type = 'P' and
  17856.                 name = 'sp_MShelpmergearticles')
  17857.         drop procedure sp_MShelpmergearticles
  17858.  
  17859.     if exists (select * from sysobjects
  17860.                 where type = 'P' and
  17861.                 name = 'sp_MShelpmergeidentity')
  17862.         drop procedure sp_MShelpmergeidentity
  17863.  
  17864.     if exists (select * from sysobjects
  17865.                 where type = 'P' and
  17866.                 name = 'sp_MShelpmergeschemaarticles')
  17867.         drop procedure sp_MShelpmergeschemaarticles
  17868.  
  17869.     if exists (select * from sysobjects
  17870.                 where type = 'P' and
  17871.                 name = 'sp_MScheckidentityrange')
  17872.         drop procedure sp_MScheckidentityrange
  17873.  
  17874.     if exists (select * from sysobjects
  17875.                 where type = 'P' and
  17876.                 name = 'sp_MSfetchidentityrange')
  17877.         drop procedure sp_MSfetchidentityrange
  17878.  
  17879.     if exists (select * from sysobjects
  17880.                 where type = 'P' and
  17881.                 name = 'sp_MScreateretry')
  17882.         drop procedure sp_MScreateretry
  17883.  
  17884.     if exists (select * from sysobjects
  17885.                 where type = 'P' and
  17886.                 name = 'sp_MSdropretry')
  17887.         drop procedure sp_MSdropretry
  17888.  
  17889.     if exists (select * from sysobjects
  17890.                 where type = 'P' and
  17891.                 name = 'sp_MSdroptemptable')
  17892.         drop procedure sp_MSdroptemptable
  17893.  
  17894.     if exists (select * from sysobjects
  17895.                 where type = 'P' and
  17896.                 name = 'sp_MSenumretries')
  17897.         drop procedure sp_MSenumretries
  17898.  
  17899.     if exists (select * from sysobjects
  17900.                 where type = 'P' and
  17901.                 name = 'sp_MSdeleteretry')
  17902.         drop procedure sp_MSdeleteretry
  17903.  
  17904.     if exists (select * from sysobjects
  17905.                 where type = 'P' and
  17906.                 name = 'sp_MSgetonerow')
  17907.         drop procedure sp_MSgetonerow
  17908.  
  17909.     if exists (select * from sysobjects
  17910.                 where type = 'P' and
  17911.                 name = 'sp_MSchangearticleresolver')
  17912.            drop procedure sp_MSchangearticleresolver
  17913.  
  17914.     if exists (select * from sysobjects
  17915.                 where type = 'P' and
  17916.                 name = 'sp_MSgetlastrecgen')
  17917.         drop procedure sp_MSgetlastrecgen
  17918.  
  17919.     if exists (select * from sysobjects
  17920.                 where type = 'P' and
  17921.                 name = 'sp_MSgetlastsentgen')
  17922.         drop procedure sp_MSgetlastsentgen
  17923.  
  17924.     if exists (select * from sysobjects
  17925.                 where type = 'P' and
  17926.                 name = 'sp_MSgetlastsentrecgens')
  17927.         drop procedure sp_MSgetlastsentrecgens
  17928.  
  17929.     if exists (select * from sysobjects
  17930.                 where type = 'P' and
  17931.                 name = 'sp_MSsetlastrecgen')
  17932.         drop procedure sp_MSsetlastrecgen
  17933.  
  17934.     if exists (select * from sysobjects
  17935.                 where type = 'P' and
  17936.                 name = 'sp_MSbelongs')
  17937.         drop procedure sp_MSbelongs
  17938.  
  17939.     if exists (select * from sysobjects
  17940.                 where type = 'P' and
  17941.                 name = 'sp_MSsetupbelongs')
  17942.         drop procedure sp_MSsetupbelongs
  17943.  
  17944.     if exists (select * from sysobjects
  17945.                 where type = 'P' and
  17946.                 name = 'sp_MSsetupworktables')
  17947.         drop procedure sp_MSsetupworktables
  17948.         
  17949.     if exists (select * from sysobjects
  17950.                 where type = 'P' and
  17951.                 name = 'sp_MSsetupnotbelongs')
  17952.         drop procedure sp_MSsetupnotbelongs
  17953.  
  17954.     if exists (select * from sysobjects
  17955.                 where type = 'P' and
  17956.                 name = 'sp_MSsetupbelongs_withoutviewproc')
  17957.         drop procedure sp_MSsetupbelongs_withoutviewproc
  17958.         
  17959.     if exists (select * from sysobjects
  17960.                 where type = 'P' and
  17961.                 name = 'sp_MSexpandbelongs')
  17962.         drop procedure sp_MSexpandbelongs
  17963.  
  17964.     if exists (select * from sysobjects
  17965.                 where type = 'P' and
  17966.                 name = 'sp_MSexpandnotbelongs')
  17967.         drop procedure sp_MSexpandnotbelongs
  17968.  
  17969.     if exists (select * from sysobjects
  17970.                 where type = 'P' and
  17971.                 name = 'sp_MSenumpartialdeletes')
  17972.         drop procedure sp_MSenumpartialdeletes
  17973.  
  17974.     if exists (select * from sysobjects
  17975.                 where type = 'P' and
  17976.                 name = 'sp_MSsetlastsentgen')
  17977.         drop procedure sp_MSsetlastsentgen
  17978.  
  17979.     if exists (select * from sysobjects
  17980.                 where type = 'P' and
  17981.                 name = 'sp_MSdummyupdate')
  17982.         drop procedure sp_MSdummyupdate 
  17983.  
  17984.     if exists (select * from sysobjects
  17985.                 where type = 'P' and
  17986.                 name = 'sp_MSdeletepushagent')
  17987.         drop procedure sp_MSdeletepushagent
  17988.         
  17989.     if exists (select * from sysobjects
  17990.                 where type = 'P' and
  17991.                 name = 'sp_MSenumgenerations')
  17992.         drop procedure sp_MSenumgenerations
  17993.  
  17994.     if exists (select * from sysobjects
  17995.                 where type = 'P' and
  17996.                 name = 'sp_MScheckexistsgeneration')
  17997.         drop procedure sp_MScheckexistsgeneration
  17998.  
  17999.     if exists (select * from sysobjects
  18000.                 where type = 'P' and
  18001.                 name = 'sp_MSenumreplicas')
  18002.         drop procedure sp_MSenumreplicas
  18003.  
  18004.     if exists (select * from sysobjects
  18005.                 where type = 'P' and
  18006.                 name = 'sp_MSenumdeletesmetadata')
  18007.         drop procedure sp_MSenumdeletesmetadata
  18008.     
  18009.     if exists (select * from sysobjects
  18010.                 where type = 'P' and
  18011.                 name = 'sp_MSenumchanges')
  18012.         drop procedure sp_MSenumchanges
  18013.     
  18014.     if exists (select * from sysobjects
  18015.                 where type = 'P' and
  18016.                 name = 'sp_MSenumpartialchanges')
  18017.         drop procedure sp_MSenumpartialchanges
  18018.  
  18019.     if exists (select * from sysobjects
  18020.                 where type = 'P' and
  18021.                 name = 'sp_MSgetrowmetadata')
  18022.         drop procedure sp_MSgetrowmetadata
  18023.     if exists (select * from sysobjects
  18024.                 where type = 'P' and
  18025.                 name = 'sp_MSgetmetadatabatch')
  18026.         drop procedure sp_MSgetmetadatabatch
  18027.  
  18028.     if exists (select * from sysobjects
  18029.                 where type = 'P' and
  18030.                 name = 'sp_MSsetrowmetadata')
  18031.         drop procedure sp_MSsetrowmetadata
  18032.  
  18033.     if exists (select * from sysobjects
  18034.                 where type = 'P' and
  18035.                 name = 'sp_MSinsertgenhistory')
  18036.         drop procedure sp_MSinsertgenhistory
  18037.  
  18038.     if exists (select * from sysobjects
  18039.                 where type = 'P' and
  18040.                 name = 'sp_MSupdategenhistory')
  18041.         drop procedure sp_MSupdategenhistory
  18042.  
  18043.     if object_id('sp_MSlocalizeinterruptedgenerations') is not null
  18044.         drop procedure sp_MSlocalizeinterruptedgenerations
  18045.  
  18046.     if exists (select * from sysobjects
  18047.                 where type = 'P' and
  18048.                 name = 'sp_MSenumschemachange')
  18049.         drop procedure sp_MSenumschemachange
  18050.  
  18051.     if exists (select * from sysobjects
  18052.                 where type = 'P' and
  18053.                 name = 'sp_MSenumschemachange_70')
  18054.         drop procedure sp_MSenumschemachange_70
  18055.  
  18056.     if exists (select * from sysobjects
  18057.                 where type = 'P' and 
  18058.                 name = 'sp_MSenumschemachange_80')
  18059.         drop procedure sp_MSenumschemachange_80
  18060.  
  18061.     if exists (select * from sysobjects
  18062.                 where type = 'P' and
  18063.                 name = 'sp_MSupdateschemachange')
  18064.         drop procedure sp_MSupdateschemachange
  18065.  
  18066.     if exists (select * from sysobjects
  18067.             where type = 'P'
  18068.                 and name = 'sp_MSadd_mergereplcommand')
  18069.         drop procedure sp_MSadd_mergereplcommand
  18070.  
  18071.     if exists (select * from sysobjects
  18072.             where type = 'P'
  18073.                 and name = 'sp_MSremove_mergereplcommand')
  18074.         drop procedure sp_MSremove_mergereplcommand
  18075.  
  18076.     if exists (select * from sysobjects
  18077.                 where type = 'P' and
  18078.                 name = 'sp_MSsetreplicainfo')
  18079.         drop procedure sp_MSsetreplicainfo
  18080.  
  18081.     if exists (select * from sysobjects
  18082.                 where type = 'P' and
  18083.                 name = 'sp_MSsetreplicastatus')
  18084.         drop procedure sp_MSsetreplicastatus
  18085.  
  18086.     if exists (select * from sysobjects
  18087.         where type = 'P'
  18088.             and name = 'sp_MScreateglobalreplica')
  18089.         drop procedure sp_MScreateglobalreplica
  18090.  
  18091.     if exists (select * from sysobjects
  18092.             where type = 'P'
  18093.                 and name = 'sp_MSsetconflictscript')
  18094.         drop procedure sp_MSsetconflictscript
  18095.  
  18096.     if exists (select * from sysobjects
  18097.             where type = 'P'
  18098.                 and name = 'sp_MSsetconflicttable')
  18099.         drop procedure sp_MSsetconflicttable
  18100.  
  18101.     if exists (select * from sysobjects
  18102.                 where type = 'P' and
  18103.                 name = 'sp_MSmakeconflictinsertproc')
  18104.         drop procedure sp_MSmakeconflictinsertproc
  18105.  
  18106.     if exists (select * from sysobjects
  18107.                 where type = 'P' and
  18108.                 name = 'sp_MSmaketempinsertproc')
  18109.         drop procedure sp_MSmaketempinsertproc
  18110.  
  18111.     if exists (select * from sysobjects
  18112.             where type = 'P'
  18113.                 and name = 'sp_MSgetconflictinsertproc')
  18114.         drop procedure sp_MSgetconflictinsertproc
  18115.  
  18116.     if exists (select * from sysobjects
  18117.                 where type = 'P' and
  18118.                 name = 'sp_MSinsertdeleteconflict')
  18119.         drop procedure sp_MSinsertdeleteconflict
  18120.  
  18121.     if exists (select * from sysobjects
  18122.                 where type = 'P' and
  18123.                 name = 'sp_MScheckmetadatamatch')
  18124.         drop procedure sp_MScheckmetadatamatch
  18125.  
  18126.     if exists (select * from sysobjects
  18127.                 where type = 'P' and
  18128.                 name = 'sp_MSdelrow')
  18129.         drop procedure sp_MSdelrow 
  18130.  
  18131.     if exists (select * from sysobjects
  18132.                 where type = 'P' and
  18133.                 name = 'sp_MSsetartprocs')
  18134.         drop procedure sp_MSsetartprocs
  18135.  
  18136.     if exists (select * from sysobjects
  18137.             where type = 'P'
  18138.                 and name = 'sp_MSmakesystableviews')
  18139.         drop procedure sp_MSmakesystableviews
  18140.  
  18141.     if exists (select * from sysobjects
  18142.             where type = 'P'
  18143.                 and name = 'sp_MSgetchangecount')
  18144.         drop procedure sp_MSgetchangecount
  18145.  
  18146.     if exists (select * from sysobjects
  18147.             where type = 'P'
  18148.                 and name = 'sp_MSuplineageversion')
  18149.         drop procedure sp_MSuplineageversion
  18150.  
  18151.     if exists (select * from sysobjects
  18152.             where type = 'P'
  18153.                 and name = 'sp_MSvalidatearticle')
  18154.         drop procedure sp_MSvalidatearticle
  18155.     if exists (select * from sysobjects
  18156.             where type = 'P'
  18157.                 and name = 'sp_MSgetviewcolumnlist')
  18158.         drop procedure sp_MSgetviewcolumnlist
  18159.     if exists (select * from sysobjects
  18160.             where type = 'P'
  18161.                 and name = 'sp_MSsubscriptionvalidated')
  18162.         drop procedure sp_MSsubscriptionvalidated
  18163.         
  18164.     if exists (select * from sysobjects
  18165.             where type = 'P'
  18166.                 and name = 'sp_MSdelsubrows')
  18167.         drop procedure sp_MSdelsubrows
  18168.         
  18169.     if exists (select * from sysobjects
  18170.             where type = 'P'
  18171.                 and name = 'sp_MSdelsubrowsbatch')
  18172.         drop procedure sp_MSdelsubrowsbatch
  18173.  
  18174.     if exists (select * from sysobjects
  18175.             where type = 'P'
  18176.                 and name = 'sp_MScontractsubsnb')
  18177.         drop procedure sp_MScontractsubsnb
  18178.  
  18179.     if exists (select * from sysobjects
  18180.             where type = 'P'
  18181.                 and name = 'sp_MSexpandsubsnb')
  18182.         drop procedure sp_MSexpandsubsnb
  18183.  
  18184.     if exists (select * from sysobjects
  18185.             where type = 'P'
  18186.                 and name = 'sp_MSmakeviewproc')
  18187.         drop procedure sp_MSmakeviewproc
  18188.  
  18189.     if exists (select * from sysobjects
  18190.             where type = 'P' and
  18191.                 name = 'sp_MScreatebeforetable')
  18192.         drop procedure sp_MScreatebeforetable 
  18193.  
  18194.     if exists (select * from sysobjects
  18195.             where type = 'P' and
  18196.                 name = 'sp_MShelpcreatebeforetable')
  18197.         drop procedure sp_MShelpcreatebeforetable 
  18198.  
  18199.     if exists (select * from sysobjects
  18200.             where type = 'P' and
  18201.                 name = 'sp_MShelpalterbeforetable')
  18202.         drop procedure sp_MShelpalterbeforetable 
  18203.  
  18204.     if exists (select * from sysobjects
  18205.             where type = 'P' and
  18206.                 name = 'sp_MSgetbeforetableinsert')
  18207.         drop procedure sp_MSgetbeforetableinsert 
  18208.  
  18209.     if exists (select * from sysobjects
  18210.             where type = 'P' and
  18211.                 name = 'sp_MSfixupbeforeimagetables')
  18212.         drop procedure sp_MSfixupbeforeimagetables 
  18213.  
  18214.     if exists (select * from sysobjects
  18215.             where type = 'P' and
  18216.                 name = 'sp_MSinserterrorlineage')
  18217.         drop procedure sp_MSinserterrorlineage 
  18218.  
  18219.     if exists (select * from sysobjects
  18220.                 where type = 'P' and
  18221.                 name = 'sp_MSevalsubscriberinfo')
  18222.         drop procedure sp_MSevalsubscriberinfo 
  18223.  
  18224.     if exists (select * from sysobjects
  18225.                 where type = 'P' and
  18226.                 name = 'sp_MSsetsubscriberinfo')
  18227.         drop procedure sp_MSsetsubscriberinfo 
  18228.  
  18229.     if exists (select * from sysobjects
  18230.                 where type = 'P' and
  18231.                 name = 'sp_MSgetsubscriberinfo')
  18232.         drop procedure sp_MSgetsubscriberinfo 
  18233.  
  18234.     if exists (select * from sysobjects
  18235.                 where type = 'P '
  18236.                 and name = 'sp_MSinsertgenerationschemachanges')
  18237.     drop procedure sp_MSinsertgenerationschemachanges
  18238.  
  18239.     if exists (select * from sysobjects
  18240.                 where type = 'P '
  18241.                 and name = 'sp_MSalreadyhavegeneration')
  18242.     drop procedure sp_MSalreadyhavegeneration
  18243.  
  18244.     if exists (select * from sysobjects
  18245.                 where type = 'P '
  18246.                 and name = 'sp_MSgettablecontents')
  18247.         drop procedure sp_MSgettablecontents
  18248.  
  18249.     if exists (select * from sysobjects
  18250.                 where type = 'P '
  18251.                 and name = 'sp_MSdelgenzero')
  18252.     drop procedure sp_MSdelgenzero
  18253.  
  18254.     if exists (select * from sysobjects
  18255.                 where type = 'P '
  18256.                 and name = 'sp_MSmakedynsnapshotvws')
  18257.     drop procedure sp_MSmakedynsnapshotvws
  18258.  
  18259.     if exists (select * from sysobjects
  18260.                 where type = 'P '
  18261.                 and name = 'sp_MSdropdynsnapshotvws')
  18262.     drop procedure sp_MSdropdynsnapshotvws
  18263.  
  18264.     if object_id('dbo.sp_MSscriptviewproc', 'P') is not null 
  18265.         drop procedure dbo.sp_MSscriptviewproc
  18266.  
  18267. go
  18268. exec dbo.sp_MS_marksystemobject sp_MSdrop_rlrecon
  18269. go
  18270.  
  18271. EXEC dbo.sp_MSdrop_rlrecon
  18272. go
  18273.  
  18274.  
  18275.  
  18276. raiserror('Creating procedure sp_MSfetchidentityrange', 0,1)
  18277. GO
  18278.  
  18279. CREATE PROCEDURE sp_MSfetchidentityrange 
  18280. @tablename            sysname,
  18281. @adjust_only        bit
  18282. AS
  18283.  
  18284. declare @retcode             int
  18285. declare @objid                int
  18286. declare @distributor        sysname
  18287. declare @distribdb            sysname
  18288. declare @publisher            sysname
  18289. declare @publisher_db        sysname
  18290. declare @next_seed            bigint
  18291. declare @range                bigint
  18292. declare @threshold            int
  18293. declare @distproc            nvarchar(300)
  18294. declare @identity_support    int
  18295. select @publisher=@@SERVERNAME
  18296. select @publisher_db=db_name()
  18297.  
  18298. select @objid = object_id(@tablename)
  18299.  
  18300. select @identity_support=identity_support from sysmergearticles where objid=@objid
  18301.  
  18302. exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  18303.         IF @@ERROR <> 0 or @retcode <> 0
  18304.             return (1)
  18305. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  18306. exec @retcode = @distproc @publisher=@publisher, 
  18307.                             @publisher_db=@publisher_db, 
  18308.                             @tablename=@tablename, 
  18309.                             @adjust_only=1, --do adjust only
  18310.                             @next_seed=@next_seed OUTPUT,
  18311.                             @range=@range OUTPUT,
  18312.                             @threshold=@threshold OUTPUT
  18313. IF @@ERROR <> 0 OR @retcode <> 0
  18314.     return (1)
  18315.  
  18316. --initialize article collection for agents.
  18317. if @adjust_only=0
  18318.     select @identity_support, @next_seed-range, range, threshold from MSrepl_identity_range where  objid = @objid
  18319. GO
  18320. exec dbo.sp_MS_marksystemobject sp_MSfetchidentityrange 
  18321. go
  18322. grant exec on dbo.sp_MSfetchidentityrange to public
  18323. go
  18324.  
  18325.  
  18326. raiserror('Creating procedure sp_MScheckidentityrange', 0,1)
  18327. GO
  18328.  
  18329. CREATE PROCEDURE sp_MScheckidentityrange 
  18330.     @pubid                 uniqueidentifier,
  18331.     @artname            sysname,
  18332.     @next_seed            bigint,
  18333.     @range                bigint,
  18334.     @threshold            int,
  18335.     @checkonly            int
  18336. AS
  18337.     declare @colid                int
  18338.     declare @colname            sysname
  18339.     declare @retcode            int
  18340.     declare @objid                int
  18341.     declare @identity_so_far    bigint
  18342.     declare @current_max        bigint
  18343.     declare @max_identity        bigint
  18344.     declare @tablename            sysname
  18345.     declare @flag                smallint
  18346.     declare @distributor        sysname
  18347.     declare @distribdb            sysname
  18348.     declare @republisher        bit
  18349.     declare @publisher            sysname
  18350.     declare @publisher_db        sysname
  18351.     declare @distproc            nvarchar(300)
  18352.     declare @pub_range            bigint
  18353.  
  18354.     
  18355.     select @objid = objid from sysmergearticles where pubid=@pubid and name=@artname
  18356.     select @flag = 1
  18357.     select @republisher = 0
  18358.     select @tablename=object_name(@objid)
  18359.  
  18360.     if exists (select * from sysmergearticles where objid=@objid and pubid <>@pubid and pubid in (select pubid from 
  18361.                     sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()))
  18362.     begin
  18363.         select @publisher=@@SERVERNAME
  18364.         select @publisher_db=db_name()
  18365.         select @republisher = 1
  18366.         exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  18367.         IF @@ERROR <> 0 or @retcode <> 0
  18368.         begin
  18369.             raiserror(14071, 16, -1)
  18370.             return (1)
  18371.             end
  18372.     end
  18373.  
  18374.     if @checkonly=1
  18375.     begin
  18376.         if @republisher=0
  18377.         begin
  18378.             --current_max is defaulted to max_identity value if not republished at subscribers.
  18379.             select @current_max = current_max from MSrepl_identity_range where objid=@objid
  18380.             select @identity_so_far = ident_current(@tablename)        
  18381.             if ident_incr(@tablename) < 0
  18382.                 select @flag = -1
  18383.             if @flag * 100 * (@identity_so_far - (@current_max + 1 - @range))/@range > @threshold
  18384.                 select 1 --needs bump up
  18385.             else
  18386.                 select 0 --no need to bump up
  18387.         end
  18388.         else
  18389.         begin
  18390.             select @current_max=0, @next_seed=0, @threshold=0, @range=0, @pub_range=0, @max_identity=0  --make them non-NULL
  18391.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  18392.             exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  18393.                                       @publisher_db=@publisher_db,
  18394.                                       @tablename=@tablename,
  18395.                                       @range=@range OUTPUT,
  18396.                                       @max_identity=@max_identity OUTPUT,
  18397.                                       @next_seed = @next_seed OUTPUT,
  18398.                                       @pub_range=@pub_range OUTPUT
  18399.             if @retcode<>0 or @@ERROR<>0
  18400.             begin
  18401.                 raiserror(21195, 16, -1) 
  18402.                 return (1)
  18403.             end
  18404.             if (@max_identity-@next_seed)<@range or (@max_identity-@next_seed)<@pub_range
  18405.                 select 1
  18406.             else
  18407.                 select 0
  18408.         end
  18409.     end
  18410.     else
  18411.     begin
  18412.         if @republisher=0
  18413.         begin
  18414.             --its current_max value is to be set by sp_addmergearticle, if to be republished.
  18415.             update MSrepl_identity_range set max_identity=@next_seed + @range, next_seed=@next_seed, current_max=@next_seed + @range -1
  18416.                 where objid = @objid
  18417.             exec sp_MSreseed @objid, @next_seed, @range 
  18418.             if @@ERROR <> 0 
  18419.                 goto FAILURE
  18420.         end
  18421.         else
  18422.         begin
  18423.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  18424.             exec @retcode = @distproc @publisher=@publisher, 
  18425.                             @publisher_db=@publisher_db, 
  18426.                             @tablename=@tablename, 
  18427.                             @for_publisher = 2,  --for repub case, increment max_identity at distributor side
  18428.                             @next_seed = @next_seed,
  18429.                             @range=@range OUTPUT,
  18430.                             @adjust_only=1 --do adjust only
  18431.             if @retcode<>0 or @@ERROR<>0
  18432.             begin
  18433.                 raiserror(21315, 16, -1, @tablename)
  18434.                 return (1)
  18435.             end
  18436.         end
  18437.     end
  18438.  
  18439.     return (0)
  18440. FAILURE:
  18441.     select 0
  18442.     return (1)
  18443. go
  18444. exec dbo.sp_MS_marksystemobject sp_MScheckidentityrange 
  18445. go
  18446. grant exec on dbo.sp_MScheckidentityrange to public
  18447. go
  18448.  
  18449. raiserror('Creating procedure sp_MShelpmergeidentity', 0,1)
  18450. GO
  18451.  
  18452. CREATE PROCEDURE sp_MShelpmergeidentity 
  18453.     @publication sysname
  18454. as
  18455.     declare @pubid                     uniqueidentifier
  18456.     declare @artid                     uniqueidentifier
  18457.     declare @nickname                int
  18458.     declare @next_seed                bigint
  18459.     declare @objid                    int
  18460.     declare @retcode                int
  18461.     declare @tablename                sysname
  18462.     declare @range                    bigint
  18463.     declare @threshold                int
  18464.     declare @distributor            sysname
  18465.     declare @distribdb                sysname
  18466.     declare @distproc                nvarchar(300)
  18467.     declare @db_name                sysname
  18468.     declare @tmp_table TABLE (tablename sysname, next_seed bigint, range bigint, threshold int, nickname int)
  18469.  
  18470.     /*
  18471.     ** To public.
  18472.     */
  18473.     set nocount on
  18474.     if (@publication is null)
  18475.         begin
  18476.         RAISERROR(14003, 16, -1)
  18477.         return (1)
  18478.         end
  18479.  
  18480.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  18481.     IF @@ERROR <> 0 or @retcode <> 0
  18482.         return (1)
  18483.     
  18484.     select @db_name = db_name()
  18485.  
  18486.     select @pubid = pubid from sysmergepublications
  18487.         where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name
  18488.  
  18489.     if (@pubid is null)
  18490.         begin
  18491.             RAISERROR (20026, 11, -1, @publication)
  18492.             return (1)
  18493.         end
  18494.     
  18495.     select TOP 1 @artid=artid from sysmergearticles where pubid=@pubid and identity_support=1 order by nickname ASC
  18496.     while (@artid is not NULL)
  18497.     begin
  18498.         select @objid=objid, @nickname=nickname from sysmergearticles 
  18499.                 where pubid=@pubid and artid=@artid
  18500.         select @tablename=object_name(@objid)
  18501.         select @next_seed=0, @threshold=0, @range=0  --make them non-NULL
  18502.  
  18503.         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  18504.         exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  18505.                                       @publisher_db=@db_name,
  18506.                                       @tablename=@tablename,
  18507.                                       @range=@range OUTPUT,
  18508.                                       @threshold=@threshold OUTPUT,
  18509.                                       @next_seed = @next_seed OUTPUT
  18510.         if @retcode<>0 or @@ERROR<>0
  18511.             return (1)
  18512.         insert @tmp_table values(@tablename, @next_seed, @range, @threshold, @nickname)
  18513.         if @@ERROR<>0
  18514.         begin
  18515.             raiserror(21197, 16, -1)
  18516.             return (1)
  18517.         end
  18518.         select @artid = NULL 
  18519.         select TOP 1 @artid=artid from sysmergearticles 
  18520.             where pubid=@pubid and nickname>@nickname and identity_support=1 order by nickname ASC
  18521.     end
  18522.     select * from  @tmp_table order by nickname ASC
  18523.     
  18524.     return (0)    
  18525. go
  18526. exec dbo.sp_MS_marksystemobject sp_MShelpmergeidentity 
  18527. go
  18528. grant exec on dbo.sp_MShelpmergeidentity to public
  18529. go
  18530.  
  18531.  
  18532. raiserror('Creating procedure sp_MShelpmergearticles', 0,1)
  18533. GO
  18534.  
  18535. CREATE PROCEDURE sp_MShelpmergearticles 
  18536.     @publication sysname,
  18537.     @compatibility_level int = 7000000,
  18538.     @pubidin uniqueidentifier = NULL
  18539. as
  18540.     declare @pubid                     uniqueidentifier
  18541.     declare @artid                     uniqueidentifier
  18542.     declare @user_name                sysname
  18543.     declare @guid_col                sysname
  18544.     declare @identity_support         int
  18545.     declare @nickname                int
  18546.     declare @identity_so_far        bigint
  18547.     declare @next_seed                bigint
  18548.     declare @pub_range                bigint
  18549.     declare @objid                    int
  18550.     declare @qualname                nvarchar(270)
  18551.     declare @retcode                int
  18552.     declare @tablename                sysname
  18553.     declare @range                    bigint
  18554.     declare @current_max            bigint
  18555.     declare @threshold                int
  18556.     declare @distributor            sysname
  18557.     declare @distribdb                sysname
  18558.     declare @distproc                nvarchar(300)
  18559.     declare @flag                    smallint
  18560.     declare @c_max                    bigint
  18561.     declare @n_seed                    bigint
  18562.     declare @db_name                sysname
  18563.     declare @has_joins                int
  18564.     declare @article_filter_category int
  18565.     declare @haspartfilters            int
  18566.     declare @grouppartfilterarticles int
  18567.     declare @injoinfilters            int
  18568.     declare @nofilters                int
  18569.     declare @objid_looper            int
  18570.     declare @indexcol                int
  18571.     declare @rowcount1                int
  18572.     declare @rowcount2                int
  18573.  
  18574.     declare @tmp_table TABLE (tablename sysname, user_name sysname,  
  18575.             guid_col sysname NULL, next_seed bigint, range bigint, threshold int, artid uniqueidentifier, pubid uniqueidentifier, has_joins int, article_filter_category int, objid int, has_relation_with_joinarticles int default 0, node_visited bit default 0)
  18576.     declare @worktable TABLE (objid int NOT NULL, indexcol int)
  18577.  
  18578.     set @nofilters = 1
  18579.     set @haspartfilters = 2
  18580.     set @injoinfilters = 4
  18581.     set @grouppartfilterarticles = 8
  18582.     
  18583.     /*
  18584.     ** To public.
  18585.     */
  18586.     set nocount on
  18587.     if (@publication is null)
  18588.         begin
  18589.         RAISERROR(14003, 16, -1)
  18590.         return (1)
  18591.         end
  18592.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  18593.         begin
  18594.         RAISERROR(20054 , 16, -1)
  18595.         return (1)
  18596.         end
  18597.  
  18598.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  18599.     IF @@ERROR <> 0 or @retcode <> 0
  18600.         return (1)
  18601.  
  18602.     
  18603.     select @db_name = db_name()
  18604.  
  18605.     if @pubidin is not NULL
  18606.         set @pubid = @pubidin
  18607.     else
  18608.         select @pubid = pubid from sysmergepublications
  18609.             where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name
  18610.  
  18611.     if (@pubid is null)
  18612.         begin
  18613.         RAISERROR (20026, 11, -1, @publication)
  18614.         return (1)
  18615.         end
  18616.  
  18617.     select TOP 1 @artid=artid from sysmergearticles where pubid=@pubid order by nickname ASC
  18618.     while (@artid is not NULL)
  18619.     begin
  18620.         select @objid=objid, @nickname=nickname, @identity_support=identity_support from sysmergearticles 
  18621.                 where pubid=@pubid and artid=@artid
  18622.         select @tablename=object_name(@objid)
  18623.         select @user_name=user_name(uid) from sysobjects where id=@objid
  18624.         select @qualname=QUOTENAME(@user_name) + '.' + QUOTENAME(@tablename)
  18625.         select @next_seed=NULL, @range=NULL, @threshold=NULL --null if not being updated later
  18626.         if @identity_support=1 and exists (select * from sysmergepublications where
  18627.             pubid = @pubid and  UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name)
  18628.         begin
  18629.             select @current_max=0, @next_seed=0, @threshold=0, @range=0, @pub_range=0  --make them non-NULL
  18630.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  18631.             exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  18632.                                       @publisher_db=@db_name,
  18633.                                       @tablename=@tablename,
  18634.                                       @range=@range OUTPUT,
  18635.                                       @current_max=@current_max OUTPUT,
  18636.                                       @threshold=@threshold OUTPUT,
  18637.                                       @next_seed = @next_seed OUTPUT,
  18638.                                       @pub_range=@pub_range OUTPUT
  18639.             if @retcode<>0 or @@ERROR<>0
  18640.                 return (1)
  18641.  
  18642.             select @identity_so_far = IDENT_CURRENT(@tablename)
  18643.             select @flag=1
  18644.             if ident_incr(@tablename) < 0
  18645.                 select @flag = -1
  18646.  
  18647.             -- we attempted to adjust publisher side identity range based on its threshodl if needed
  18648.             -- however, non-dbo/sysadmin's will not be able to do so.
  18649.             -- so this is limited to dbos or sysadmins.
  18650.             if @flag * 100 * (@identity_so_far - (@current_max + 1 - @pub_range))/@pub_range > @threshold
  18651.                     and ((is_srvrolemember('sysadmin') = 1) or (is_member('db_owner') = 1)) 
  18652.             begin
  18653.                 select @c_max=@next_seed + @pub_range - 1
  18654.                 select @n_seed=@next_seed + @pub_range
  18655.                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadjust_pub_identity'
  18656.                 exec  @retcode=@distproc @publisher=@@SERVERNAME,
  18657.                                         @publisher_db=@db_name,
  18658.                                         @tablename=@tablename,
  18659.                                         @current_max=@c_max,
  18660.                                         @next_seed = @n_seed
  18661.                 if @retcode<>0 or @@ERROR<>0
  18662.                     return (1)
  18663.  
  18664.                 exec @retcode=sp_MSreseed @objid, @next_seed, @pub_range, 1
  18665.                 if @@ERROR <> 0 or @retcode<>0
  18666.                 begin
  18667.                     raiserror(21197, 16, -1)
  18668.                     return (1)
  18669.                 end
  18670.                 select @next_seed=@next_seed + @pub_range
  18671.  
  18672.             end
  18673.         end
  18674.         else if @identity_support=1 and not exists (select * from sysmergepublications where
  18675.             pubid = @pubid and  UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name)
  18676.         begin
  18677.             /* This is the case of a message based subscriber acting like publisher */
  18678.             select @range = range, @threshold = threshold, @next_seed = next_seed
  18679.                 from MSrepl_identity_range where objid = @objid
  18680.         end
  18681.  
  18682.         if exists (select * from sysmergesubsetfilters where join_nickname = @nickname)
  18683.             set @has_joins = 1
  18684.         else 
  18685.             set @has_joins = 0
  18686.  
  18687.         -- reset for subsequent bitwise OR operations.
  18688.         set @article_filter_category = 0
  18689.  
  18690.         if exists (select * from sysmergesubsetfilters where pubid = @pubid and (join_nickname = @nickname or art_nickname = @nickname))
  18691.             set @article_filter_category = (@article_filter_category | @injoinfilters)
  18692.         
  18693.         if exists (select * from sysmergearticles where pubid = @pubid and nickname = @nickname and datalength(subset_filterclause) > 1)
  18694.             set @article_filter_category = (@article_filter_category | @haspartfilters | @grouppartfilterarticles)
  18695.         
  18696.         if (@article_filter_category = 0)
  18697.             set @article_filter_category = @nofilters
  18698.  
  18699.         select @guid_col=name from syscolumns where id=@objid and ColumnProperty(@objid, name, 'IsRowGuidCol')=1
  18700.         insert @tmp_table values(@tablename, @user_name, @guid_col, 
  18701.             @next_seed, @range, @threshold, @artid, @pubid, @has_joins, @article_filter_category, @objid, 0, 0)
  18702.         if @@ERROR<>0
  18703.         begin
  18704.             raiserror(21197, 16, -1)
  18705.             return (1)
  18706.         end
  18707.         select @artid = NULL 
  18708.         select TOP 1 @artid=artid from sysmergearticles 
  18709.             where pubid=@pubid and nickname>@nickname order by nickname ASC
  18710.     end
  18711.  
  18712.     -- Find articles that have no relations (in either direction - referring or referenced) with any articles in the join filter category.
  18713.  
  18714.     if exists (select * from @tmp_table where (article_filter_category & @injoinfilters) = @injoinfilters)
  18715.     begin
  18716.  
  18717.         --create unique index #uncworktable on @worktable(objid, indexcol)
  18718.         update @tmp_table set node_visited = 1 
  18719.         where objid not in (select fkeyid from sysreferences)
  18720.         and objid not in (select rkeyid from sysreferences)
  18721.         and (article_filter_category & @injoinfilters) = 0
  18722.  
  18723.         -- get the min objid from the temp table of all articles
  18724.         select @objid_looper = min(objid) from @tmp_table where node_visited = 0
  18725.         
  18726.         while (@objid_looper is not null)
  18727.         begin
  18728.             delete from @worktable
  18729.  
  18730.             select @indexcol = 0
  18731.  
  18732.             insert into @worktable values (@objid_looper, @indexcol)
  18733.                         
  18734.             -- find all the objects referenced by this object and all objects that reference this object.
  18735.             insert into @worktable select distinct rkeyid, @indexcol+1 from sysreferences where fkeyid = @objid_looper
  18736.                                             and rkeyid not in (select objid from @worktable)
  18737.             select @rowcount1 = @@rowcount
  18738.             
  18739.             insert into @worktable select distinct fkeyid, @indexcol+1 from sysreferences where rkeyid = @objid_looper
  18740.                                             and fkeyid not in (select objid from @worktable)
  18741.             select @rowcount2 = @@rowcount
  18742.             
  18743.             while (@rowcount1 <> 0 or @rowcount2 <> 0)
  18744.             begin
  18745.                 
  18746.                 select @indexcol = @indexcol+1
  18747.  
  18748.                 insert into @worktable select distinct s.rkeyid, @indexcol+1 from sysreferences s, @worktable w, @tmp_table t where s.fkeyid = w.objid and w.objid = t.objid
  18749.                                             and w.indexcol = @indexcol and t.node_visited = 0 and s.rkeyid not in (select objid from @worktable)
  18750.                 select @rowcount1 = @@rowcount
  18751.                 
  18752.                 insert into @worktable select distinct s.fkeyid, @indexcol+1 from sysreferences s, @worktable w, @tmp_table t where s.rkeyid = w.objid and w.objid = t.objid
  18753.                                             and w.indexcol = @indexcol and t.node_visited = 0 and s.fkeyid not in (select objid from @worktable)
  18754.                 select @rowcount2 = @@rowcount
  18755.             end
  18756.  
  18757.             if exists (select * from @worktable w, @tmp_table t where w.objid = t.objid and (t.article_filter_category & @injoinfilters) = @injoinfilters)
  18758.             begin
  18759.                 -- all articles in @worktable have a direct or indirect relation with at least one object in the join articles category.
  18760.                 update @tmp_table set node_visited = 1, has_relation_with_joinarticles = 1 
  18761.                 from @tmp_table t, @worktable w 
  18762.                 where w.objid = t.objid 
  18763.             end
  18764.             else
  18765.             begin
  18766.                 -- none of the articles in @worktable has any relation (direct or indirect) with any article in the join articles category.            
  18767.                 update @tmp_table set node_visited = 1, has_relation_with_joinarticles = 0 
  18768.                 from @tmp_table t, @worktable w 
  18769.                 where w.objid = t.objid 
  18770.             end
  18771.  
  18772.             -- process more unvisited articles from @tmp_table
  18773.             select @objid_looper = min(objid) from @tmp_table where objid > @objid_looper and node_visited = 0
  18774.         end
  18775.     end
  18776.     
  18777.     /* If the 7.0 merge agent is making this call then we need to make sure that the CLSID of the sp resolver is the old one and not the new one */
  18778.     if @compatibility_level = 7000000
  18779.         begin
  18780.             begin transaction 
  18781.                 update sysmergearticles set resolver_clsid = '{6F31CE30-7BE4-11d1-9B0A-00C04FC2DEB3}' where article_resolver = 'Microsoft SQLServer Stored Procedure Resolver'
  18782.                 select name, t.tablename, t.user_name, a.artid, pre_creation_command, a.pubid, nickname,
  18783.                     column_tracking, status, resolver_clsid, conflict_script, conflict_table,
  18784.                     insert_proc, update_proc, select_proc, destination_object, missing_col_count, 
  18785.                     missing_cols, t.guid_col, 
  18786.                     article_resolver, resolver_info, subset_filterclause, has_joins, excluded_col_count, 
  18787.                     excluded_cols, destination_owner, identity_support, t.next_seed, t.range, t.threshold, 
  18788.                     verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, t.article_filter_category, t.has_relation_with_joinarticles
  18789.                 from sysmergearticles a, @tmp_table t
  18790.                 where a.artid=t.artid and a.pubid=t.pubid order by a.nickname
  18791.             rollback transaction                
  18792.         end
  18793.     else
  18794.         begin
  18795.             select name, t.tablename, t.user_name, a.artid, pre_creation_command, a.pubid, nickname,
  18796.                 column_tracking, status, resolver_clsid, conflict_script, conflict_table,
  18797.                 insert_proc, update_proc, select_proc, destination_object, missing_col_count, 
  18798.                 missing_cols, t.guid_col, 
  18799.                 article_resolver, resolver_info, subset_filterclause, has_joins, excluded_col_count, 
  18800.                 excluded_cols, destination_owner, identity_support, t.next_seed, t.range, t.threshold, 
  18801.                 verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, t.article_filter_category, t.has_relation_with_joinarticles
  18802.             from sysmergearticles a, @tmp_table t
  18803.             where a.artid=t.artid and a.pubid=t.pubid order by a.nickname
  18804.         end            
  18805.  
  18806.     return (0)    
  18807. go
  18808. exec dbo.sp_MS_marksystemobject sp_MShelpmergearticles 
  18809. go
  18810. grant exec on dbo.sp_MShelpmergearticles to public
  18811. go
  18812.  
  18813. raiserror('Creating procedure sp_MShelpmergeschemaarticles', 0,1)
  18814. go
  18815.  
  18816. CREATE PROCEDURE sp_MShelpmergeschemaarticles
  18817.     @publication sysname
  18818. as
  18819. begin
  18820.     set nocount on
  18821.  
  18822.     declare @pubid         uniqueidentifier
  18823.     declare @db_name       sysname
  18824.  
  18825.     if (@publication is null)
  18826.     begin
  18827.         raiserror(14003, 16, -1)
  18828.         return (1)
  18829.     end
  18830.  
  18831.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  18832.     begin
  18833.         raiserror(20054, 16, -1)
  18834.         return (1)
  18835.     end
  18836.     
  18837.     select @db_name = db_name()
  18838.     select @pubid = pubid from dbo.sysmergepublications
  18839.         where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db = @db_name
  18840.  
  18841.     if (@pubid is null)
  18842.     begin
  18843.         raiserror(20026, 11, -1, @publication)
  18844.         return (1)
  18845.     end
  18846.  
  18847.  
  18848.     select a.name, o.name, user_name(o.uid), a.destination_object, a.destination_owner, a.artid, @pubid, a.pre_creation_command, a.status, a.type 
  18849.       from dbo.sysmergeschemaarticles a
  18850.     inner join sysobjects o
  18851.         on a.objid = o.id 
  18852.         where pubid = @pubid 
  18853.  
  18854.     return 0
  18855. end
  18856. go
  18857. exec dbo.sp_MS_marksystemobject sp_MShelpmergeschemaarticles 
  18858. go
  18859. grant exec on dbo.sp_MShelpmergeschemaarticles to public
  18860. go
  18861.  
  18862.  
  18863. raiserror('Creating procedure sp_MScreateretry', 0,1)
  18864. GO
  18865.  
  18866. CREATE PROCEDURE sp_MScreateretry 
  18867. as
  18868.     declare @tname sysname
  18869.     declare @pname sysname
  18870.     declare @tempname sysname
  18871.     declare @guid uniqueidentifier
  18872.     declare @guidstr varchar(40)
  18873.     declare @retcode smallint
  18874.  
  18875.     /*
  18876.     ** To public.
  18877.     */
  18878.     
  18879.     set @guid = newid()
  18880.     exec @retcode=sp_MSguidtostr @guid, @guidstr out
  18881.     if @retcode<>0 or @@ERROR<>0 return (1)
  18882.     set @tempname = '##retry_' + @guidstr
  18883.  
  18884.     exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
  18885.     if (@@error <> 0) OR @retcode <> 0
  18886.         begin
  18887.         RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
  18888.         return (1)
  18889.         end
  18890.  
  18891.     exec ('create table ' + @tempname + ' (tablenick int NOT NULL, rowguid uniqueidentifier ROWGUIDCOL default newid() not null, errcode int NOT NULL, errtext nvarchar(255) NULL, type tinyint NOT NULL)' )
  18892.  
  18893.     if (@@error <> 0)
  18894.         begin
  18895.         RAISERROR(15001, 16, -1, @tempname)
  18896.         return (1)
  18897.         end
  18898.  
  18899.     set     @tname = @tempname
  18900.     set @tempname = '##insert_' + @guidstr
  18901.  
  18902.     exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
  18903.     if (@@error <> 0)
  18904.         begin
  18905.         RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
  18906.         return (1)
  18907.         end
  18908.  
  18909.     exec @retcode = dbo.sp_MSmaketempinsertproc @tname, @tempname
  18910.     if  @@ERROR <>0 or @retcode<>0 return (1)
  18911.  
  18912.     select @pname = @tempname
  18913.     select @tname, @pname
  18914.     return (0)    
  18915. go
  18916. exec dbo.sp_MS_marksystemobject sp_MScreateretry 
  18917. go
  18918. grant exec on dbo.sp_MScreateretry to public
  18919.  
  18920. raiserror('Creating procedure sp_MSdropretry', 0,1)
  18921. GO
  18922.  
  18923. CREATE PROCEDURE sp_MSdropretry (@tname sysname, @pname sysname)
  18924. as
  18925.     declare @retcode int
  18926.     /*
  18927.     ** To public
  18928.     */
  18929.     
  18930.     exec ('drop table ' + @tname)
  18931.     if @@ERROR <> 0 return(1)
  18932.     exec ('drop procedure ' + @pname)
  18933.     if @@ERROR <> 0 return(1)
  18934.     return (0)    
  18935. go
  18936. exec dbo.sp_MS_marksystemobject sp_MSdropretry 
  18937. go
  18938. grant exec on dbo.sp_MSdropretry to public
  18939. go
  18940.  
  18941. raiserror('Creating procedure sp_MSdroptemptable', 0,1)
  18942. GO
  18943. CREATE PROCEDURE sp_MSdroptemptable (@tname sysname)
  18944. as
  18945.     if exists(select * from tempdb.dbo.sysobjects where name = @tname) 
  18946.     begin
  18947.         exec ('drop table ' + @tname)
  18948.         
  18949.         if @@ERROR <> 0 
  18950.             return(1)
  18951.     end
  18952.     
  18953.     return (0)    
  18954. go
  18955. exec dbo.sp_MS_marksystemobject sp_MSdroptemptable 
  18956. go
  18957. grant exec on dbo.sp_MSdroptemptable to public
  18958. go
  18959.  
  18960. raiserror('Creating procedure sp_MSchangearticleresolver', 0,1)
  18961. GO
  18962.  
  18963. CREATE PROCEDURE sp_MSchangearticleresolver (
  18964. @article_resolver         nvarchar(255),
  18965. @resolver_clsid            nvarchar(40),
  18966. @artid                    uniqueidentifier,
  18967. @resolver_info            sysname = NULL
  18968. )
  18969. as
  18970.     if (@resolver_clsid='') select @resolver_clsid = NULL
  18971.     UPDATE sysmergearticles
  18972.         SET article_resolver = @article_resolver, resolver_clsid = @resolver_clsid, resolver_info = @resolver_info
  18973.         WHERE artid = @artid
  18974.     if @@ERROR <> 0 
  18975.           RETURN (1)
  18976.     return (0)     
  18977. go
  18978.  
  18979. exec dbo.sp_MS_marksystemobject sp_MSchangearticleresolver
  18980. go
  18981.  
  18982. -- ****************************************************
  18983. -- THIS COMMENTED CODE SECTION WILL BE DELETED SOON
  18984. -- sp_MSgetversion is now part of XPSTAR.DLL and 
  18985. -- will not be installed by REPL code
  18986.  
  18987. --raiserror('Creating sp_MSgetversion', 0,1)
  18988. --GO
  18989. if not exists (select * from sysobjects where name = 'sp_MSgetversion')
  18990. begin
  18991.     exec dbo.sp_addextendedproc 'sp_MSgetversion', 'xpstar.dll'
  18992.     exec dbo.sp_MS_marksystemobject sp_MSgetversion
  18993.     grant exec on dbo.sp_MSgetversion to public
  18994. end
  18995. go
  18996. -- ****************************************************
  18997.  
  18998. raiserror('Creating procedure sp_MSenumretries', 0,1)
  18999. GO
  19000.  
  19001. CREATE PROCEDURE sp_MSenumretries
  19002.     (@tname nvarchar(386),
  19003.      @maxrows int,
  19004.      @tablenick int,
  19005.      @rowguid uniqueidentifier)
  19006. as
  19007.     declare @tnstring nvarchar(12)
  19008.     declare @rgstring nvarchar(38)
  19009.     declare @retcode int
  19010.     
  19011.     /*
  19012.     ** Modify temp table, granted to public.
  19013.     */
  19014.  
  19015.     declare @selecttop nvarchar(20)
  19016.     if (@maxrows = 0)
  19017.         set @selecttop= 'select'
  19018.     else
  19019.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  19020.     
  19021.     if (@tablenick < 1)
  19022.     begin
  19023.         execute (@selecttop + ' tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
  19024.                  ' order by tablenick, rowguidcol')
  19025.         IF @@ERROR <>0 RETURN (1)          
  19026.     end
  19027.     else
  19028.     begin
  19029.         set @tnstring = convert(nchar, @tablenick)
  19030.         set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  19031.         execute (@selecttop + ' tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
  19032.                 ' where (tablenick = ' + @tnstring + ' and  rowguidcol > ' + @rgstring + ') or
  19033.                      tablenick > ' + @tnstring + ' order by tablenick, rowguidcol' )
  19034.         if @@ERROR <> 0 RETURN (1)
  19035.     end
  19036.     return (0)    
  19037. go
  19038. exec dbo.sp_MS_marksystemobject sp_MSenumretries
  19039. go
  19040. grant exec on dbo.sp_MSenumretries to public
  19041.  
  19042. raiserror('Creating procedure sp_MSdeleteretry', 0,1)
  19043. GO
  19044.  
  19045. CREATE PROCEDURE sp_MSdeleteretry 
  19046.     (@temptable nvarchar(386),
  19047.      @tablenick int,
  19048.      @rowguid uniqueidentifier)
  19049. as
  19050.     declare @guidstr nvarchar(38)
  19051.     declare @nickstr nvarchar(12)
  19052.     declare @retcode int
  19053.     
  19054.     /*
  19055.     ** Modify temp table, granted to public.
  19056.     */
  19057.     
  19058.     set @nickstr = convert(nchar, @tablenick)
  19059.     set @guidstr = '''' + convert(nchar(36), @rowguid) + ''''
  19060.  
  19061.     execute ('delete from ' + @temptable + ' where tablenick = ' +
  19062.               @nickstr + ' and rowguidcol = ' + @guidstr)
  19063.     IF @@ERROR <>0 RETURN (1)
  19064.     return (0)
  19065. go
  19066. exec dbo.sp_MS_marksystemobject sp_MSdeleteretry 
  19067. go
  19068. grant exec on dbo.sp_MSdeleteretry to public
  19069. go
  19070.  
  19071. raiserror('Creating procedure sp_MSdeletepushagent', 0,1)
  19072. GO
  19073.  
  19074. /*
  19075. ** This procedure is obselete for dropping push agent at distribution database.
  19076. ** If we were to recover, don't use server id as parameter for RPC into distributor.
  19077. ** Use server name instead.
  19078. */
  19079. CREATE PROCEDURE sp_MSdeletepushagent (
  19080.     @publisher             sysname,
  19081.     @publisher_db         sysname,
  19082.     @publication         sysname,
  19083.     @subscriber             sysname,
  19084.     @subscriber_db         sysname
  19085.     ) AS
  19086.  
  19087. declare @distributor     sysname
  19088. declare @distribdb        sysname
  19089. declare @pubid            uniqueidentifier
  19090. declare @distproc        nvarchar(300)
  19091. declare @pub_srvid        smallint
  19092. declare @sub_srvid        smallint
  19093. declare @retcode        smallint
  19094.  
  19095. EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  19096.         IF @@ERROR <> 0 or @retcode <> 0
  19097.             return (1)
  19098.         
  19099. select @pub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  19100. select @sub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  19101. select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  19102.  
  19103. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_agent_entry'
  19104.  
  19105. EXEC @retcode = @distproc @pub_srvid, @publisher_db, @publication, @sub_srvid, @subscriber_db
  19106.         IF @@ERROR <> 0 OR @retcode <> 0
  19107.             return (1)
  19108. return (0)
  19109. GO
  19110. exec dbo.sp_MS_marksystemobject sp_MSdeletepushagent
  19111. go
  19112. grant exec on dbo.sp_MSdeletepushagent to public
  19113. go
  19114.  
  19115. raiserror('Creating procedure sp_MSgetonerow', 0,1)
  19116. GO
  19117.  
  19118. CREATE PROCEDURE sp_MSgetonerow
  19119.     (@tablenick int,
  19120.      @rowguid uniqueidentifier,
  19121.      @pubid uniqueidentifier = NULL)
  19122. as
  19123.     declare @retcode     smallint
  19124.     declare @procname    sysname
  19125.  
  19126.     /*
  19127.     ** Check to see if current publication has permission
  19128.     */
  19129.     if sessionproperty('replication_agent') = 0
  19130.     begin
  19131.         exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  19132.         if @retcode<>0 or @@ERROR<>0 return (1)
  19133.     end
  19134.     
  19135.     select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid=@pubid
  19136.     
  19137.     exec @retcode = @procname @type =1, @rowguid=@rowguid
  19138.     IF @@ERROR<>0 or @retcode<>0 RETURN (1)
  19139.     return (0)
  19140. go
  19141. exec dbo.sp_MS_marksystemobject sp_MSgetonerow
  19142. go
  19143. grant exec on dbo.sp_MSgetonerow to public
  19144. go
  19145.  
  19146. raiserror('Creating procedure sp_MSuplineageversion', 0,1)
  19147. GO
  19148.  
  19149. CREATE PROCEDURE sp_MSuplineageversion
  19150.     (@tablenick int,
  19151.      @rowguid uniqueidentifier,
  19152.      @version int)
  19153. as
  19154.     declare @replnick int
  19155.     declare @curversion int
  19156.     declare @lineage varbinary(255)
  19157.     declare @retcode int
  19158.     declare @colv varbinary(2048)
  19159.     declare @col_tracking int
  19160.     declare @rowintombstone int
  19161.     
  19162.     /*
  19163.     ** Check to see if current publication has permission
  19164.     */
  19165.     if sessionproperty('replication_agent') = 0
  19166.     begin
  19167.         exec @retcode=sp_MSreplcheck_connection
  19168.             @tablenick = @tablenick
  19169.         if @retcode<>0 or @@ERROR<>0 return (1)
  19170.     end
  19171.     
  19172.     exec dbo.sp_MSgetreplnick @nickname = @replnick out
  19173.     if (@@error <> 0) or @replnick IS NULL 
  19174.         begin
  19175.         RAISERROR (14055, 11, -1)
  19176.         RETURN(1)
  19177.         end                 
  19178.     if (@rowguid is null)
  19179.         begin
  19180.         RAISERROR(14043, 16, -1, '@rowguid')
  19181.         return (1)
  19182.         end
  19183.     if (@tablenick is null)
  19184.         begin
  19185.         RAISERROR(14043, 16, -1, '@tablenick')
  19186.         return (1)
  19187.         end
  19188.  
  19189.     select @col_tracking = column_tracking
  19190.              from sysmergearticles where nickname = @tablenick
  19191.  
  19192.     begin transaction
  19193.     save tran sp_MSuplineageversion
  19194.  
  19195.     -- get lineage, locking row in MSmerge_contents. If not found there, also try MSmerge_tombstone
  19196.     set @rowintombstone= 0
  19197.     select @lineage = lineage, @colv = colv1 from dbo.MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  19198.             rowguid = @rowguid
  19199.     if (@lineage is null)
  19200.     begin
  19201.         select @lineage = lineage from dbo.MSmerge_tombstone (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  19202.             rowguid = @rowguid
  19203.         set @colv= NULL
  19204.         set @rowintombstone= 1
  19205.     end
  19206.     if (@lineage is null)
  19207.     begin
  19208.         RAISERROR(14043, 16, -1, '@lineage')
  19209.         goto Failure
  19210.     end
  19211.  
  19212.     set @curversion = 0
  19213.     while (@curversion < @version)
  19214.     begin
  19215.         set @lineage= { fn UPDATELINEAGE(@lineage, @replnick, 1) }
  19216.         set @curversion= { fn GETMAXVERSION(@lineage) }
  19217.         IF @@ERROR<>0 goto Failure
  19218.     end
  19219.     if (@col_tracking = 0 or @colv is NULL)
  19220.         set @colv = NULL
  19221.     else
  19222.         set @colv = { fn UPDATECOLVBM(@colv, @replnick, 0x01, 0x00, @curversion) }
  19223.         
  19224.     -- update lineage in MSmerge_contents or MSmerge_tombstone
  19225.     if (@rowintombstone = 0)
  19226.     begin
  19227.         update dbo.MSmerge_contents set lineage = @lineage, colv1 = @colv where 
  19228.             tablenick = @tablenick and rowguid = @rowguid
  19229.     end
  19230.     else
  19231.     begin
  19232.         update dbo.MSmerge_tombstone set lineage = @lineage where
  19233.             tablenick = @tablenick and rowguid = @rowguid
  19234.     end
  19235.  
  19236.     commit
  19237.     return (0)
  19238. Failure:
  19239.     rollback tran sp_MSuplineageversion
  19240.     commit tran
  19241.     return(1)
  19242. go
  19243. exec dbo.sp_MS_marksystemobject sp_MSuplineageversion
  19244. go
  19245. grant exec on dbo.sp_MSuplineageversion to public
  19246.  
  19247. raiserror('Creating procedure sp_MSgetlastrecgen', 0,1)
  19248. GO
  19249.  
  19250. CREATE PROCEDURE sp_MSgetlastrecgen
  19251.     (@repid uniqueidentifier)
  19252. as
  19253.     declare @pubid         uniqueidentifier
  19254.     declare @pubname     sysname
  19255.     declare @status     int
  19256.     declare @retcode    int
  19257.  
  19258.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19259.         begin
  19260.         RAISERROR(20054 , 16, -1)
  19261.         return (1)
  19262.         end
  19263.  
  19264.     if (@repid is null)
  19265.         begin
  19266.             RAISERROR(14043, 16, -1, '@repid')
  19267.             return (1)
  19268.         end
  19269.     /*
  19270.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19271.     ** metadata cleanup event then return an error so the current merge will quit.
  19272.     */
  19273.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  19274.     if (@pubid is not null)
  19275.         begin
  19276.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19277.             IF @retcode = 0
  19278.                 BEGIN
  19279.  
  19280.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19281.                     if @status = 0
  19282.                         begin
  19283.                             RAISERROR(21505, 16, -1, @pubname)
  19284.                             return (1)
  19285.                         end
  19286.                 END
  19287.         end
  19288.  
  19289.     select recgen, recguid from MSmerge_replinfo where repid = @repid
  19290.     return (0)
  19291. go
  19292. exec dbo.sp_MS_marksystemobject sp_MSgetlastrecgen
  19293. go
  19294. grant exec on dbo.sp_MSgetlastrecgen to public
  19295.  
  19296. raiserror('Creating procedure sp_MSgetlastsentgen', 0,1)
  19297. GO
  19298.  
  19299. CREATE PROCEDURE sp_MSgetlastsentgen
  19300.     (@repid uniqueidentifier)
  19301. as
  19302.     declare @pubid         uniqueidentifier
  19303.     declare @pubname     sysname
  19304.     declare @status     int
  19305.     declare @retcode    int
  19306.  
  19307.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19308.         begin
  19309.         RAISERROR(20054 , 16, -1)
  19310.         return (1)
  19311.         end
  19312.  
  19313.     if (@repid is null)
  19314.         begin
  19315.             RAISERROR(14043, 16, -1, '@repid')
  19316.             return (1)
  19317.         end
  19318.     /*
  19319.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19320.     ** metadata cleanup event then return an error so the current merge will quit.
  19321.     */
  19322.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  19323.     if (@pubid is not null)
  19324.         begin
  19325.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19326.             IF @retcode = 0
  19327.                 BEGIN
  19328.  
  19329.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19330.                     if @status = 0
  19331.                         begin
  19332.                             RAISERROR(21505, 16, -1, @pubname)
  19333.                             return (1)
  19334.                         end
  19335.                 END
  19336.         end
  19337.  
  19338.     select sentgen, sentguid from MSmerge_replinfo where repid = @repid
  19339.     return (0)
  19340. go
  19341. exec dbo.sp_MS_marksystemobject sp_MSgetlastsentgen
  19342. go
  19343. grant exec on dbo.sp_MSgetlastsentgen to public
  19344. go
  19345.  
  19346. raiserror('Creating procedure sp_MSgetlastsentrecgens', 0,1)
  19347. GO
  19348.  
  19349. CREATE PROCEDURE sp_MSgetlastsentrecgens
  19350.     (@repid uniqueidentifier)
  19351. as
  19352.     declare @pubid         uniqueidentifier
  19353.     declare @pubname     sysname
  19354.     declare @status     int
  19355.     declare @retcode    int
  19356.  
  19357.     if (@repid is null)
  19358.         begin
  19359.             RAISERROR(14043, 16, -1, '@repid')
  19360.             return (1)
  19361.         end
  19362.     /*
  19363.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19364.     ** metadata cleanup event then return an error so the current merge will quit.
  19365.     */
  19366.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  19367.     if (@pubid is not null)
  19368.         begin
  19369.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19370.             IF @retcode = 0
  19371.                 BEGIN
  19372.  
  19373.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19374.                     if @status = 0
  19375.                         begin
  19376.                             RAISERROR(21505, 16, -1, @pubname)
  19377.                             return (1)
  19378.                         end
  19379.                 END
  19380.         end
  19381.  
  19382.     select sentgen, sentguid, recgen, recguid from MSmerge_replinfo where repid = @repid
  19383.     return (0)
  19384. go
  19385. exec dbo.sp_MS_marksystemobject sp_MSgetlastsentrecgens
  19386. go
  19387. grant exec on dbo.sp_MSgetlastsentrecgens to public
  19388.  
  19389. raiserror('Creating procedure sp_MSdummyupdate', 0,1)
  19390. GO
  19391.  
  19392.  
  19393. CREATE PROCEDURE sp_MSdummyupdate
  19394.     (@rowguid uniqueidentifier, @tablenick int, @metatype tinyint, @pubid uniqueidentifier = NULL, @uplineage tinyint = 1, @inlineage varbinary(255) = NULL, @incolv varbinary(2048) = NULL)
  19395. as
  19396.     declare @retcode     int
  19397.     declare @lineage     varbinary(255)
  19398.     declare    @conflict_lineage varbinary(255)
  19399.     declare @mynickname     int
  19400.     declare @col_tracking int
  19401.     declare @colv varbinary(2048)
  19402.     declare @reason nvarchar(255)
  19403.     declare @oldmaxversion int
  19404.  
  19405.     /*
  19406.     ** Check to see if current publication has permission
  19407.     */
  19408.     if sessionproperty('replication_agent') = 0
  19409.     begin
  19410.         exec @retcode=sp_MSreplcheck_connection
  19411.             @tablenick = @tablenick
  19412.         if @retcode<>0 or @@ERROR<>0 return (1)
  19413.     end
  19414.     
  19415.     /* Parameter checks */
  19416.     if (@rowguid is null)
  19417.         begin
  19418.         RAISERROR(14043, 16, -1, '@rowguid')
  19419.         return (1)
  19420.         end
  19421.     if (@tablenick is null)
  19422.         begin
  19423.         RAISERROR(14043, 16, -1, '@tablenick')
  19424.         return (1)
  19425.         end
  19426.     if (@metatype is null)
  19427.         begin
  19428.         RAISERROR(14043, 16, -1, '@metatype')
  19429.         return (1)
  19430.         end
  19431.  
  19432.     /* Check if we have a merge publication by whether system table is there */
  19433.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19434.         begin
  19435.         RAISERROR(20054 , 16, -1)
  19436.         return (1)
  19437.         end
  19438.  
  19439.     exec dbo.sp_MSgetreplnick @nickname = @mynickname out
  19440.     if (@@error <> 0) or @mynickname IS NULL 
  19441.         begin
  19442.         RAISERROR (14055, 11, -1)
  19443.         RETURN(1)
  19444.         end                 
  19445.  
  19446.     -- Look for the "other" lineage in a conflict table
  19447.     select @conflict_lineage = max(lineage) from MSmerge_errorlineage where
  19448.         rowguid = @rowguid and tablenick = @tablenick
  19449.  
  19450.     set @oldmaxversion= (select top 1 maxversion_at_cleanup from sysmergearticles 
  19451.                             where nickname = @tablenick)
  19452.  
  19453.     if (@metatype = 0)
  19454.     begin
  19455.         /* We don't have the row.  Putting in a system delete tombstone should cause a delete and
  19456.         ** eventual convergence.  We are already logging the row as a conflict / error.
  19457.         */
  19458.         if @conflict_lineage is not null
  19459.         begin
  19460.             set @lineage = { fn UPDATELINEAGE(@conflict_lineage, @mynickname, @oldmaxversion+1) }
  19461.         end
  19462.         else
  19463.         begin
  19464.             set @lineage = { fn UPDATELINEAGE(0x0, @mynickname, @oldmaxversion+1) }
  19465.         end
  19466.         select @reason = formatmessage(20564) -- system delete
  19467.     
  19468.         insert into dbo.MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) 
  19469.             values (@rowguid, @tablenick, 6, @lineage, 0, @reason)
  19470.         
  19471.     end
  19472.     else if (@metatype = 1)
  19473.     begin
  19474.         if @inlineage is not null
  19475.         begin
  19476.             set @lineage = @inlineage
  19477.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname, @oldmaxversion+1) }
  19478.         end
  19479.         else
  19480.         begin
  19481.             select @lineage = lineage from dbo.MSmerge_tombstone (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  19482.                 rowguid = @rowguid
  19483.             if (@uplineage = 1)
  19484.             begin
  19485.                 if @conflict_lineage is not null
  19486.                 begin
  19487.                     exec @retcode= master..xp_mergelineages @lineage, @conflict_lineage, @lineage output
  19488.                     if @@error<>0 or @retcode<>0 return(1)
  19489.                 end
  19490.                 set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname, @oldmaxversion+1) }
  19491.             end
  19492.         end
  19493.             
  19494.         update dbo.MSmerge_tombstone set generation = 0, lineage = @lineage where
  19495.             tablenick = @tablenick and rowguid = @rowguid
  19496.     end
  19497.     else if (@metatype = 2)
  19498.     begin
  19499.         if @inlineage is not null
  19500.         begin
  19501.             set @lineage = @inlineage
  19502.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname, @oldmaxversion+1) }
  19503.  
  19504.             if @incolv is not null
  19505.             begin
  19506.                 set @colv = @incolv
  19507.             end
  19508.             else
  19509.             begin
  19510.                 select @colv = colv1 from dbo.MSmerge_contents (UPDLOCK ROWLOCK index = 1) where 
  19511.                     tablenick = @tablenick and rowguid = @rowguid
  19512.                 if @pubid is NULL
  19513.                     select @col_tracking = column_tracking from sysmergearticles where nickname = @tablenick
  19514.                 else
  19515.                     select @col_tracking = column_tracking from sysmergearticles where nickname = @tablenick and pubid = @pubid
  19516.                 if (@col_tracking = 0 or @colv is NULL)
  19517.                     set @colv = NULL
  19518.                 else
  19519.                     set @colv = { fn UPDATECOLVBM(@colv, @mynickname, 0x01, 0x00, { fn GETMAXVERSION(@lineage) }) }
  19520.             end
  19521.         end
  19522.         else
  19523.             -- @inlineage is null -> @incolv is null, too
  19524.         begin
  19525.             select @lineage = lineage, @colv = colv1 from dbo.MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and
  19526.                 rowguid = @rowguid
  19527.             if (@uplineage = 1)
  19528.             begin
  19529.                 if @conflict_lineage is not null
  19530.                 begin
  19531.                     exec @retcode= master..xp_mergelineages @lineage, @conflict_lineage, @lineage output
  19532.                     if @@error<>0 or @retcode<>0 return(1)
  19533.                 end
  19534.                 set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname, @oldmaxversion+1) }
  19535.                 if @pubid is NULL
  19536.                     select @col_tracking = column_tracking from sysmergearticles where nickname = @tablenick
  19537.                 else
  19538.                     select @col_tracking = column_tracking from sysmergearticles where nickname = @tablenick and pubid = @pubid
  19539.                 if (@col_tracking = 0 or @colv is NULL)
  19540.                     set @colv = NULL
  19541.                 else
  19542.                     set @colv = { fn UPDATECOLVBM(@colv, @mynickname, 0x01, 0x00, { fn GETMAXVERSION(@lineage) }) }
  19543.             end
  19544.         end
  19545.  
  19546.         update dbo.MSmerge_contents set generation = 0, lineage = @lineage, colv1 = @colv where
  19547.             tablenick = @tablenick and rowguid = @rowguid
  19548.     end
  19549.     else if (@metatype = 3)
  19550.     begin
  19551.         declare @ccols         int
  19552.         declare @sync_objid     int
  19553.         declare @missing_count int
  19554.  
  19555.         if @inlineage is not null
  19556.         begin
  19557.             set @lineage = @inlineage
  19558.             set @lineage = { fn UPDATELINEAGE(@lineage, @mynickname, @oldmaxversion+1) }
  19559.         end
  19560.         else if @conflict_lineage is not null
  19561.         begin
  19562.             set @lineage = { fn UPDATELINEAGE(@conflict_lineage, @mynickname, @oldmaxversion+1) }
  19563.         end
  19564.         else
  19565.         begin
  19566.             set @lineage = { fn UPDATELINEAGE(0x0, @mynickname, @oldmaxversion+1) }
  19567.         end
  19568.  
  19569.         if @incolv is not null
  19570.         begin
  19571.             set @colv = @incolv
  19572.         end
  19573.         else
  19574.         begin
  19575.             if @pubid is NULL
  19576.             begin
  19577.                 select @sync_objid = sync_objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  19578.                  from sysmergearticles where nickname = @tablenick
  19579.             end
  19580.             else
  19581.             begin
  19582.                 select @sync_objid = sync_objid, @col_tracking = column_tracking, @missing_count = missing_col_count
  19583.                  from sysmergearticles where nickname = @tablenick and pubid = @pubid
  19584.             end
  19585.  
  19586.             if (@col_tracking = 0)
  19587.                 set @colv = NULL
  19588.             else
  19589.             begin
  19590.                 select @ccols= count(*) from syscolumns where id = @sync_objid
  19591.                 set @ccols = @ccols + @missing_count
  19592.                 set @colv = { fn INITCOLVS(@ccols, @mynickname ) }
  19593.             end
  19594.         end
  19595.  
  19596.         insert into dbo.MSmerge_contents (tablenick, rowguid, lineage, generation, colv1)
  19597.             values (@tablenick, @rowguid, @lineage, 0, @colv)
  19598.     end
  19599.     else if (@metatype = 6) -- e.g., used to cope with dup key / dup index
  19600.     begin
  19601.         if @conflict_lineage is not null
  19602.         begin
  19603.             set @lineage = { fn UPDATELINEAGE(@conflict_lineage, @mynickname, @oldmaxversion+1) }
  19604.         end
  19605.         else
  19606.         begin
  19607.             set @lineage = { fn UPDATELINEAGE(0x0, @mynickname, @oldmaxversion+1) }
  19608.         end
  19609.         select @reason = formatmessage(20564) -- system delete
  19610.     
  19611.         begin transaction
  19612.             if not exists (select * from MSmerge_tombstone where rowguid=@rowguid and tablenick=@tablenick)
  19613.             begin
  19614.                 insert into dbo.MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) 
  19615.                     values (@rowguid, @tablenick, @metatype, @lineage, 0, @reason)
  19616.             end
  19617.             delete from dbo.MSmerge_contents where rowguid=@rowguid and tablenick=@tablenick
  19618.         commit
  19619.     end
  19620.     return (0)
  19621. go
  19622. exec dbo.sp_MS_marksystemobject sp_MSdummyupdate
  19623. go
  19624. grant exec on dbo.sp_MSdummyupdate to public
  19625. go
  19626.  
  19627.  
  19628. raiserror('Creating procedure sp_MSsetlastrecgen', 0,1)
  19629. GO
  19630.  
  19631. CREATE PROCEDURE sp_MSsetlastrecgen
  19632.     (@repid uniqueidentifier, @srcgen int, @srcguid uniqueidentifier)
  19633. as
  19634.     /*
  19635.     ** Check to see if current publication has permission
  19636.     */
  19637.     declare @retcode     int
  19638.     declare @pubid         uniqueidentifier
  19639.     declare @pubname     sysname
  19640.     declare @status     int
  19641.  
  19642.     if sessionproperty('replication_agent') = 0
  19643.     begin
  19644.         exec @retcode=sp_MSreplcheck_connection
  19645.             @repid = @repid
  19646.         if @retcode<>0 or @@ERROR<>0 return (1)
  19647.     end
  19648.  
  19649.     if (@repid is null)
  19650.         begin
  19651.         RAISERROR(14043, 16, -1, '@repid')
  19652.         return (1)
  19653.         end
  19654.     if (@srcgen is null)
  19655.         begin
  19656.         RAISERROR(14043, 16, -1, '@srcgen')
  19657.         return (1)
  19658.         end
  19659.     if (@srcguid is null)
  19660.         begin
  19661.         RAISERROR(14043, 16, -1, '@srcguid')
  19662.         return (1)
  19663.         end
  19664.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19665.         begin
  19666.         RAISERROR(20054 , 16, -1)
  19667.         return (1)
  19668.         end
  19669.  
  19670.     /*
  19671.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19672.     ** metadata cleanup event then return an error so the current merge will quit.
  19673.     */
  19674.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  19675.     if (@pubid is not null)
  19676.         begin
  19677.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19678.             IF @retcode = 0
  19679.                 BEGIN
  19680.  
  19681.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19682.                     if @status = 0
  19683.                         begin
  19684.                             RAISERROR(21505, 16, -1, @pubname)
  19685.                             return (1)
  19686.                         end
  19687.                 END
  19688.         end
  19689.  
  19690.     update MSmerge_replinfo set recgen = @srcgen, recguid = @srcguid 
  19691.         where repid = @repid
  19692.     IF @@ERROR <>0 return (1) 
  19693.     return (0)
  19694. go
  19695. exec dbo.sp_MS_marksystemobject sp_MSsetlastrecgen
  19696. go
  19697. grant exec on dbo.sp_MSsetlastrecgen to public
  19698. go
  19699.  
  19700.  
  19701. dump tran master with no_log
  19702. go
  19703.  
  19704. raiserror('Creating procedure sp_MSsetlastsentgen', 0,1)
  19705. GO
  19706.  
  19707. CREATE PROCEDURE sp_MSsetlastsentgen
  19708.     (@repid uniqueidentifier, @srcgen int, @srcguid uniqueidentifier)
  19709. as
  19710.     /*
  19711.     ** Check to see if current publication has permission
  19712.     */
  19713.     declare @retcode     int
  19714.     declare @pubid         uniqueidentifier
  19715.     declare @pubname     sysname
  19716.     declare @status     int
  19717.  
  19718.     if sessionproperty('replication_agent') = 0
  19719.     begin    
  19720.         exec @retcode=sp_MSreplcheck_connection
  19721.             @repid = @repid
  19722.         if @retcode<>0 or @@ERROR<>0 return (1)
  19723.     end
  19724.  
  19725.     if (@repid is null)
  19726.         begin
  19727.         RAISERROR(14043, 16, -1, '@repid')
  19728.         return (1)
  19729.         end
  19730.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19731.         begin
  19732.         RAISERROR(20054 , 16, -1)
  19733.         return (1)
  19734.         end
  19735.  
  19736.     /*
  19737.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19738.     ** metadata cleanup event then return an error so the current merge will quit.
  19739.     */
  19740.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  19741.     if (@pubid is not null)
  19742.         begin
  19743.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19744.             IF @retcode = 0
  19745.                 BEGIN
  19746.  
  19747.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19748.                     if @status = 0
  19749.                         begin
  19750.                             RAISERROR(21505, 16, -1, @pubname)
  19751.                             return (1)
  19752.                         end
  19753.                 END
  19754.         end
  19755.  
  19756.  
  19757.     /* 
  19758.     ** This is a special case which is used to update the anonymous subscriptions sent and 
  19759.     ** received generation guids at the end of initializing a dynamic subscription. This is 
  19760.     ** used in the case where an anonymous subscription is reinitialized after a merge metadata
  19761.     ** cleanup
  19762.     */
  19763.     if (@srcgen is null and @srcguid is null)
  19764.         begin
  19765.  
  19766.             declare @minnullgen         int
  19767.             declare @lastrecsentgen     int
  19768.             declare @lastrecsentguid     uniqueidentifier
  19769.             select @minnullgen = min(generation) from dbo.MSmerge_genhistory where guidlocal = '00000000-0000-0000-0000-000000000000'
  19770.             if @minnullgen IS NOT NULL
  19771.                 select @lastrecsentgen = max(generation) from dbo.MSmerge_genhistory where generation < @minnullgen
  19772.             if @lastrecsentgen IS NOT NULL
  19773.                 select @lastrecsentguid = guidsrc from dbo.MSmerge_genhistory where generation = @lastrecsentgen
  19774.             update MSmerge_replinfo  set sentgen= @lastrecsentgen, sentguid = @lastrecsentguid, recgen = @lastrecsentgen, recguid = @lastrecsentguid
  19775.                 where repid = @repid
  19776.             IF @@ERROR <>0 return (1)
  19777.         end
  19778.     else
  19779.         begin
  19780.             -- check for setting a sentgen which is obviously too high
  19781.             if (exists (select * from dbo.MSmerge_genhistory where generation < @srcgen and
  19782.                         guidlocal = '00000000-0000-0000-0000-000000000000' and
  19783.                         (art_nick = 0 or art_nick is null or art_nick in
  19784.                             (select nickname from sysmergearticles where
  19785.                                     pubid = @pubid) )))
  19786.                 begin
  19787.                 RAISERROR('Setting sentgen too high', 16, -1)
  19788.                 return (1)
  19789.                 end
  19790.             update MSmerge_replinfo  set sentgen= @srcgen, sentguid = @srcguid 
  19791.                 where repid = @repid
  19792.             IF @@ERROR <>0 return (1)
  19793.         end            
  19794.     return (0)
  19795. go
  19796. exec dbo.sp_MS_marksystemobject sp_MSsetlastsentgen
  19797. go
  19798. grant exec on dbo.sp_MSsetlastsentgen to public
  19799. go
  19800.  
  19801.  
  19802. raiserror('Creating procedure sp_MSenumgenerations', 0,1)
  19803. GO
  19804.  
  19805. CREATE PROCEDURE sp_MSenumgenerations
  19806.     (@genstart int, @pubid uniqueidentifier, @return_count_of_generations bit = 0)
  19807. as
  19808.     declare @retcode     smallint
  19809.     declare @guidnull     uniqueidentifier
  19810.     declare @generation_range TABLE (generation int NOT NULL, guidsrc uniqueidentifier NOT NULL, art_nick int NULL, guidlocal uniqueidentifier NOT NULL, pubid uniqueidentifier NULL, nicknames varbinary(1000) NOT NULL, okaytoskip bit NOT NULL)
  19811.     declare @status     int
  19812.     declare @pubname     sysname
  19813.     declare @rowcount    int
  19814.     set @guidnull = '00000000-0000-0000-0000-000000000000'
  19815.         
  19816.     /*
  19817.     ** To public
  19818.     */
  19819.     
  19820.     if (@genstart is null)
  19821.         begin
  19822.         RAISERROR(14043, 16, -1, '@genstart')
  19823.         return (1)
  19824.         end
  19825.     if (@pubid is null)
  19826.         begin
  19827.         RAISERROR(14043, 16, -1, '@pubid')
  19828.         return (1)
  19829.         end
  19830.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19831.         begin
  19832.         RAISERROR(20054 , 16, -1)
  19833.         return (1)
  19834.         end
  19835.     /*
  19836.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  19837.     ** metadata cleanup event then return an error so the current merge will quit.
  19838.     */
  19839.     EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  19840.     IF @retcode = 0
  19841.         BEGIN
  19842.  
  19843.             select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  19844.             if @status = 0
  19845.                 begin
  19846.                     RAISERROR(21505, 16, -1, @pubname)
  19847.                     return (1)
  19848.                 end
  19849.         END
  19850.  
  19851.     insert into @generation_range (generation, guidsrc, art_nick, guidlocal, pubid, nicknames, okaytoskip)
  19852.     select DISTINCT generation, guidsrc, art_nick, guidlocal, pubid, nicknames, 0
  19853.     from dbo.MSmerge_genhistory 
  19854.     where generation >= @genstart 
  19855.     and (art_nick = 0 or art_nick is NULL or 
  19856.         art_nick in (select nickname from sysmergearticles 
  19857.         where pubid = @pubid)) 
  19858.     select @rowcount = @@rowcount
  19859.  
  19860.     if (@return_count_of_generations = 1)
  19861.         select @rowcount
  19862.  
  19863.     -- optimizations 
  19864.     -- 1. skip all rows that are for incomplete generations for articles that have no joins.
  19865.     -- 2. skip all rows for join articles if all the join article rows are incomplete generations.
  19866.  
  19867.     update @generation_range set okaytoskip = 1
  19868.     where art_nick is not null and art_nick <> 0
  19869.     and guidlocal = @guidnull 
  19870.     and 
  19871.     (
  19872.         (    
  19873.             -- 1. skip all rows that are for incomplete generations for articles that have no joins.
  19874.             not exists (select 1 from sysmergesubsetfilters where join_nickname = art_nick or art_nickname = art_nick)
  19875.         )
  19876.         or
  19877.         (    
  19878.             -- 2. skip all rows for join articles if all the rows for join and joined articles (i.e. the articles represented by join_nickname 
  19879.             --    and art_nickname in sysmergesubsetfilters) are incomplete generations.
  19880.  
  19881.             art_nick in (select join_nickname from sysmergesubsetfilters) 
  19882.             and not exists 
  19883.                 (    
  19884.                     select 1 from @generation_range b where b.guidlocal <> @guidnull 
  19885.                     and exists (select 1 from sysmergesubsetfilters where join_nickname = b.art_nick or art_nickname = b.art_nick)
  19886.                     and b.generation > @genstart
  19887.                 ) 
  19888.         )
  19889.     )
  19890.     
  19891.     select generation, guidsrc, art_nick, guidlocal, pubid, nicknames, okaytoskip from @generation_range
  19892.     ORDER BY generation ASC
  19893.  
  19894.     return (0)
  19895. go
  19896. exec dbo.sp_MS_marksystemobject sp_MSenumgenerations
  19897. go
  19898. grant exec on dbo.sp_MSenumgenerations to public
  19899. go
  19900. raiserror('Creating procedure sp_MScheckexistsgeneration', 0,1)
  19901. GO
  19902.  
  19903. CREATE PROCEDURE sp_MScheckexistsgeneration
  19904.     (@genguid uniqueidentifier, @gen int output, @pubid uniqueidentifier = NULL)
  19905. as
  19906.     /*
  19907.     ** Check input parameter
  19908.     */
  19909.     if (@genguid is null)
  19910.         begin
  19911.             RAISERROR(14043, 16, -1, '@genguid')
  19912.             return (1)
  19913.         end
  19914.  
  19915.     /* Normal case : do not qualify by pubid */
  19916.     if (@pubid IS NULL)
  19917.         select @gen = max(generation) from dbo.MSmerge_genhistory where guidsrc = @genguid and guidlocal <> '00000000-0000-0000-0000-000000000000'
  19918.     else        
  19919.     /* If we are reinitializing from an alternate publisher, check if the subscription has received generations for the alternate publication */
  19920.         select @gen = max(generation) from dbo.MSmerge_genhistory where guidsrc = @genguid and guidlocal <> '00000000-0000-0000-0000-000000000000'
  19921.             and ((pubid = @pubid) or (pubid is null))
  19922.     IF @@ERROR <>0 return (1)
  19923.     return (0)
  19924. go
  19925. exec dbo.sp_MS_marksystemobject sp_MScheckexistsgeneration
  19926. go
  19927. grant exec on dbo.sp_MScheckexistsgeneration to public
  19928. GO
  19929.  
  19930. CREATE PROCEDURE sp_MSchecksnapshotstatus
  19931.     @publication        sysname
  19932. AS
  19933.     declare @db_name        sysname
  19934.     declare @retention        int
  19935.     declare @snapshot_ready    int
  19936.     declare @pubid            uniqueidentifier
  19937.     declare @last_snapshot     datetime
  19938.     
  19939.     select @snapshot_ready = NULL
  19940.     select @db_name = db_name()
  19941.     select @snapshot_ready=snapshot_ready, @retention=retention, @pubid=pubid
  19942.         from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=@db_name
  19943.     if @snapshot_ready is NULL
  19944.         select @snapshot_ready=snapshot_ready, @retention=retention, @pubid=pubid
  19945.             from sysmergepublications where name=@publication
  19946.     if @snapshot_ready is NULL
  19947.     begin
  19948.         raiserror (20026, 11, -1, @publication)
  19949.         return (1)
  19950.     end
  19951.     
  19952.     if @snapshot_ready=1 and @retention>0
  19953.     begin
  19954.         select @last_snapshot=last_validated from sysmergesubscriptions where subid=@pubid
  19955.         if dateadd(day, @retention, @last_snapshot)<getdate()
  19956.             select @snapshot_ready=3 /* snapshot is obsolete */
  19957.     end
  19958.     select @snapshot_ready
  19959. go
  19960. exec dbo.sp_MS_marksystemobject sp_MSchecksnapshotstatus
  19961. go
  19962. grant exec on dbo.sp_MSchecksnapshotstatus to public
  19963.  
  19964. raiserror('Creating procedure sp_MSenumreplicas', 0,1)
  19965. GO
  19966.  
  19967. CREATE PROCEDURE sp_MSenumreplicas (@pubid uniqueidentifier)
  19968. as
  19969.     declare @inactive tinyint
  19970.  
  19971.     /*
  19972.     ** To public
  19973.     */
  19974.  
  19975.     select @inactive = 0
  19976.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  19977.     begin
  19978.         RAISERROR(20054 , 16, -1)
  19979.         return (1)
  19980.     end
  19981.  
  19982.     select subs.subid, replinfo.replnickname, subs.subscriber_type, subs.subscription_type, 
  19983.         subs.priority, replinfo.schemaversion, replinfo.schemaguid, subs.datasource_type, subs.datasource_path, servers.srvname,  
  19984.         subs.db_name, subs.status, subs.partnerid, subs.sync_type, subs.description, subs.pubid, subs.publication, subs.distributor
  19985.         from sysmergesubscriptions subs, MSmerge_replinfo replinfo, master..sysservers servers
  19986.             where replinfo.repid = subs.subid 
  19987.                 and subs.srvid = servers.srvid
  19988.                 and subs.status <> @inactive
  19989.                 and subs.subscriber_type = 1
  19990.                 order by convert(binary, subs.subid)
  19991.     IF @@ERROR <>0 return (1) 
  19992.     return (0)
  19993. go
  19994. exec dbo.sp_MS_marksystemobject sp_MSenumreplicas 
  19995. go
  19996. grant exec on dbo.sp_MSenumreplicas to public
  19997.  
  19998. raiserror('Creating procedure sp_MSenumdeletesmetadata', 0,1)
  19999. GO
  20000.  
  20001. CREATE PROCEDURE sp_MSenumdeletesmetadata(
  20002.     @pubid uniqueidentifier, 
  20003.     @maxrows int, 
  20004.     @genlist varchar(8000), 
  20005.     @tablenick int, 
  20006.     @rowguid     uniqueidentifier,
  20007.     @filter_partialdeletes int = 0,
  20008.     @specified_article_only int = 0,
  20009.     @mingen    int = 0,
  20010.     @maxgen int = 0)
  20011. as
  20012.     declare @tnstring nvarchar(12)
  20013.     declare @rgstring nvarchar(38)
  20014.     declare @pubidstr nvarchar(38)
  20015.     declare @tablenick_qual nvarchar(100)
  20016.     declare @maxgenmingen_clause nvarchar(100)
  20017.  
  20018.     /*
  20019.     ** To public.
  20020.     */
  20021.     
  20022.     if (@genlist is null)
  20023.     begin
  20024.         RAISERROR(14043, 16, -1, '@genlist')
  20025.         return (1)
  20026.     end
  20027.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  20028.     begin
  20029.         RAISERROR(20054 , 16, -1)
  20030.         return (1)
  20031.     end
  20032.             
  20033.  
  20034.     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  20035.  
  20036.     /* If the filter_partialdeletes is NOT set, include all types of tombstones, else filter the type = 5 ones */
  20037.     if (@filter_partialdeletes = 0)
  20038.         set @tablenick_qual = '    and ts.tablenick = sm.nickname '
  20039.     else
  20040.         set @tablenick_qual = '    and ts.tablenick = sm.nickname and ts.type <> 5'
  20041.     
  20042.     declare @selecttop nvarchar(20)
  20043.     if (@maxrows = 0)
  20044.         set @selecttop= 'select'
  20045.     else
  20046.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  20047.     
  20048.     declare @mingenstr nvarchar(13)
  20049.     declare @maxgenstr nvarchar(13)
  20050.  
  20051.     select @mingenstr = convert(nchar, @mingen)
  20052.     select @maxgenstr = convert(nchar, @maxgen)
  20053.  
  20054.     if (@maxgen = 0)
  20055.         select @maxgenmingen_clause = ' '
  20056.     else
  20057.         select @maxgenmingen_clause = ' generation >= ' + @mingenstr + ' and generation <= ' + @maxgenstr + ' and '
  20058.  
  20059.     if (@tablenick = 0)
  20060.     begin
  20061.         if (@genlist is not null and rtrim(ltrim(@genlist)) <> '')
  20062.         begin
  20063.             execute (@selecttop + ' tablenick, rowguid, generation, lineage, ts.type from dbo.MSmerge_tombstone ts, sysmergearticles sm
  20064.                 where ' + @maxgenmingen_clause + ' generation in (' + @genlist + ') 
  20065.                 and sm.pubid = ' + @pubidstr + @tablenick_qual + '
  20066.                 order by tablenick desc, rowguid asc' )
  20067.  
  20068.             IF @@ERROR <>0 
  20069.             begin
  20070.                 return (1)     
  20071.             end
  20072.  
  20073.  
  20074.         end
  20075.     end
  20076.     else
  20077.     begin
  20078.         set @tnstring = convert(nchar, @tablenick)
  20079.         set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  20080.         if (@genlist is not null and rtrim(ltrim(@genlist)) <> '')
  20081.         begin
  20082.             if (@specified_article_only = 1)
  20083.             begin
  20084.                 execute (@selecttop + ' tablenick, rowguid, generation, lineage, ts.type from dbo.MSmerge_tombstone ts, sysmergearticles sm
  20085.                     where ' + @maxgenmingen_clause + ' generation in (' + @genlist + ') and 
  20086.                     tablenick = ' + @tnstring + ' and 
  20087.                     rowguid > ' + @rgstring + ' 
  20088.                     and sm.pubid = ' + @pubidstr + @tablenick_qual + ' 
  20089.                     order by rowguid' )
  20090.  
  20091.                 IF @@ERROR <>0 
  20092.                 begin
  20093.                     return (1)     
  20094.                 end
  20095.  
  20096.             end
  20097.             else
  20098.             begin
  20099.                 execute (@selecttop + ' tablenick, rowguid, generation, lineage, ts.type from dbo.MSmerge_tombstone ts, sysmergearticles sm
  20100.                     where ' + @maxgenmingen_clause + ' generation in (' + @genlist + ') and 
  20101.                     ((tablenick = ' + @tnstring + ' and 
  20102.                     rowguid > ' + @rgstring + ') or
  20103.                     tablenick < ' + @tnstring + ') 
  20104.                     and sm.pubid = ' + @pubidstr + @tablenick_qual + ' 
  20105.                     order by tablenick desc, rowguid asc' )
  20106.  
  20107.                 IF @@ERROR <>0 
  20108.                 begin
  20109.                     return (1)     
  20110.                 end
  20111.  
  20112.             end
  20113.         end
  20114.     end
  20115.  
  20116.     return (0)
  20117. go
  20118. exec dbo.sp_MS_marksystemobject sp_MSenumdeletesmetadata 
  20119. go
  20120. grant exec on dbo.sp_MSenumdeletesmetadata to public
  20121. go
  20122. raiserror('Creating procedure sp_MSenumpartialdeletes', 0,1)
  20123. GO
  20124.  
  20125. CREATE PROCEDURE sp_MSenumpartialdeletes
  20126.     (@maxrows int,
  20127.      @tablenick int,
  20128.      @rowguid uniqueidentifier,
  20129.      @tablenotbelongs nvarchar(255),
  20130.      @bookmark int = NULL,
  20131.      @specified_article_only int = 0)
  20132. as
  20133.  
  20134.     declare @tnstring         nvarchar(12)
  20135.     declare @rgstring         nvarchar(38)
  20136.     declare @lowrangestr     nvarchar(12) 
  20137.     declare @highrangestr     nvarchar(12) 
  20138.  
  20139.     /*
  20140.     ** To public.
  20141.     */
  20142.     
  20143.     declare @selecttop nvarchar(20)
  20144.     if (@maxrows = 0)
  20145.         set @selecttop= 'select'
  20146.     else
  20147.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  20148.  
  20149.  
  20150.     if (@tablenick < 1)
  20151.     begin
  20152.         execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  20153.                     order by tablenick desc, rowguid asc' )
  20154.         IF @@ERROR <>0 
  20155.         begin
  20156.             return (1)     
  20157.         end
  20158.  
  20159.     end
  20160.     else 
  20161.     begin
  20162.         set @tnstring = convert(nchar, @tablenick)
  20163.         set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  20164.  
  20165.         /* 
  20166.         ** If a 7.0 SP1 Merge agent is calling this sp, it passed a valid bookmark parameter 
  20167.         ** Use the bookmark column in the ##belongs_<> table to retrieve the next batch of rows
  20168.         */
  20169.         if @bookmark is NOT NULL 
  20170.         begin
  20171.             set @lowrangestr = convert(nchar, @bookmark)
  20172.             set @highrangestr = convert(nchar, (@bookmark + @maxrows))
  20173.  
  20174.             if (@specified_article_only = 1)
  20175.             begin
  20176.                 -- don't rely on @highrangestr since it will be equal to @lowrangestr if @maxrows=0.
  20177.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  20178.                             where  tablenick = ' + @tnstring + ' and 
  20179.                             bookmark > ' + @lowrangestr + ' 
  20180.                             order by rowguid' )
  20181.  
  20182.                 if @@ERROR<>0
  20183.                 begin
  20184.                     return (1)
  20185.                 end                        
  20186.  
  20187.  
  20188.             end
  20189.             else
  20190.             begin
  20191.                 execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  20192.                             where  ((tablenick = ' + @tnstring + ' and 
  20193.                             bookmark > ' + @lowrangestr + ' and bookmark <= ' + @highrangestr + ') or
  20194.                             tablenick < ' + @tnstring + ') 
  20195.                             order by tablenick desc, rowguid asc' )
  20196.  
  20197.                 if @@ERROR<>0
  20198.                 begin
  20199.                     return (1)
  20200.                 end                        
  20201.  
  20202.             end
  20203.         end
  20204.  
  20205.         /* 
  20206.         ** Backward compatibilty mode : If a 7.0 Merge agent is calling this sp, it will pass a NULL bookmark parameter 
  20207.         ** Use the rowguid and set rowcount to retrieve the next batch of rows
  20208.         */
  20209.         else
  20210.         begin
  20211.             if (@specified_article_only = 1)
  20212.             begin
  20213.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
  20214.                             where  tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring + '
  20215.                             order by rowguid' )
  20216.                 IF @@ERROR <>0 
  20217.                 begin
  20218.                     return (1)     
  20219.                 end
  20220.  
  20221.             end
  20222.             else
  20223.             begin
  20224.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
  20225.                             where  ((tablenick = ' + @tnstring + ' and 
  20226.                             rowguid > ' + @rgstring + ') or tablenick < ' + @tnstring + ') 
  20227.                             order by tablenick desc, rowguid asc' )
  20228.                 IF @@ERROR <>0 
  20229.                 begin
  20230.                     return (1)     
  20231.                 end
  20232.  
  20233.             end
  20234.         end
  20235.     end
  20236.     return (0)
  20237. go        
  20238. exec dbo.sp_MS_marksystemobject sp_MSenumpartialdeletes
  20239. go
  20240. grant exec on dbo.sp_MSenumpartialdeletes to public
  20241. go
  20242.  
  20243.  
  20244. raiserror('Creating procedure sp_MSenumchanges', 0,1)
  20245. GO
  20246. CREATE PROCEDURE sp_MSenumchanges
  20247.     (@maxrows int, @genlist varchar(8000), @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL,
  20248.         @oldmaxgen int=0, @mingen    int = 0, @maxgen int = 0)
  20249. as
  20250.     declare @tnstring    nvarchar(12)
  20251.     declare @oldmaxgenstr  nvarchar(12)
  20252.     declare @rgstring     nvarchar(38)
  20253.     declare @retcode     smallint
  20254.     declare @procname    nvarchar(270)
  20255.     declare @maxgenmingen_clause nvarchar(100)
  20256.  
  20257.     /*
  20258.     ** To public.
  20259.     */
  20260.     if (@tablenick is null)
  20261.     begin
  20262.         RAISERROR(14043, 16, -1, '@tablenick')
  20263.         return (1)
  20264.     end
  20265.     if (@genlist is null)
  20266.     begin
  20267.         RAISERROR(14043, 16, -1, '@genlist')
  20268.         return (1)
  20269.     end
  20270.  
  20271.     create table #cont (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, generation int NULL, lineage varbinary(249) NULL    , colv1 varbinary(2048) NULL)
  20272.     
  20273.     set @tnstring = convert(nchar, @tablenick)
  20274.     set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  20275.  
  20276.     declare @selecttop nvarchar(20)
  20277.     if (@maxrows = 0)
  20278.         set @selecttop= 'select'
  20279.     else
  20280.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  20281.  
  20282.     declare @mingenstr nvarchar(13)
  20283.     declare @maxgenstr nvarchar(13)
  20284.  
  20285.     select @mingenstr = convert(nchar, @mingen)
  20286.     select @maxgenstr = convert(nchar, @maxgen)
  20287.  
  20288.     if (@maxgen = 0)
  20289.         select @maxgenmingen_clause = ' '
  20290.     else
  20291.         select @maxgenmingen_clause = ' generation >= ' + @mingenstr + ' and generation <= ' + @maxgenstr + ' and '
  20292.  
  20293.     if (@genlist is not null and rtrim(ltrim(@genlist)) <> '')
  20294.     begin
  20295.         if @oldmaxgen > 0
  20296.         begin
  20297.         set @oldmaxgenstr = convert(nchar, @oldmaxgen)
  20298.         execute ('insert into #cont ' +
  20299.                     @selecttop + ' tablenick, rowguid, generation, lineage, colv1
  20300.                              from dbo.MSmerge_contents where 
  20301.                             (
  20302.                                 (
  20303.                                     ' + @maxgenmingen_clause + ' generation in (' + @genlist + ')
  20304.                                 )
  20305.                                 or generation = 0 or generation > ' + @oldmaxgenstr + '
  20306.                             ) 
  20307.                             and tablenick = ' + @tnstring + ' 
  20308.                             and rowguid > ' + @rgstring +     ' 
  20309.                             order by rowguid' )
  20310.         end
  20311.         else
  20312.         execute ('insert into #cont ' +
  20313.                     @selecttop + ' tablenick, rowguid, generation, lineage, colv1
  20314.                              from dbo.MSmerge_contents where ' + @maxgenmingen_clause + ' generation in (' + @genlist + ') and 
  20315.                         tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring +
  20316.                             ' order by rowguid' )
  20317.         if @@ERROR <>0 
  20318.         begin
  20319.             return (1)
  20320.         end
  20321.     end
  20322.  
  20323.     select @procname = select_proc from sysmergearticles where nickname=@tablenick and pubid = @pubid
  20324.     exec @retcode = @procname @type=2
  20325.     IF @@ERROR<>0 or @retcode<>0
  20326.     begin
  20327.         RETURN (1)
  20328.     end
  20329.  
  20330.  
  20331.  
  20332.     drop table #cont
  20333.     return (0)
  20334. go
  20335. exec dbo.sp_MS_marksystemobject sp_MSenumchanges
  20336. go
  20337. grant exec on dbo.sp_MSenumchanges to public
  20338. go
  20339.  
  20340. raiserror('Creating procedure sp_MSenumpartialchanges', 0,1)
  20341. GO
  20342.  
  20343. CREATE PROCEDURE sp_MSenumpartialchanges
  20344.     (@maxrows int, @temp_cont sysname, @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL)
  20345. as
  20346.     declare @retcode         smallint
  20347.     declare @tnstring         nvarchar(12)
  20348.     declare @rgstring         nvarchar(38)
  20349.     -- Owner qualified
  20350.     declare @procname        nvarchar(270)
  20351.     /*
  20352.     ** To public.
  20353.     */
  20354.     
  20355.     if (@tablenick is null)
  20356.         begin
  20357.         RAISERROR(14043, 16, -1, '@tablenick')
  20358.         return (1)
  20359.         end
  20360.     
  20361.     set @tnstring = convert(nchar, @tablenick)
  20362.     set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  20363.  
  20364.     create table #cont (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, generation int NULL, lineage varbinary(249) NULL    ,colv1 varbinary(2048) NULL)
  20365.     
  20366.     declare @selecttop nvarchar(20)
  20367.     if (@maxrows = 0)
  20368.         set @selecttop= 'select'
  20369.     else
  20370.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  20371.     
  20372.     execute ('insert into #cont ' +
  20373.                     @selecttop + ' tablenick, rowguid, generation, lineage, colv from ' + @temp_cont + ' where
  20374.                             tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring
  20375.                             + ' order by rowguid')
  20376.     if @@ERROR<>0
  20377.     begin
  20378.         return (1)
  20379.     end                        
  20380.  
  20381.     select @procname = select_proc from sysmergearticles where nickname=@tablenick and pubid = @pubid
  20382.     
  20383.     exec @retcode = @procname @type =3
  20384.     IF @@ERROR<>0 or @retcode<>0 
  20385.     begin
  20386.         RETURN (1)
  20387.     end
  20388.  
  20389.  
  20390.  
  20391.     drop table #cont
  20392.     return (0)
  20393. go
  20394. exec dbo.sp_MS_marksystemobject sp_MSenumpartialchanges
  20395. go
  20396. grant exec on dbo.sp_MSenumpartialchanges to public
  20397.  
  20398.  
  20399. raiserror('Creating procedure sp_MSinitdynamicsubscriber', 0,1)
  20400. GO
  20401.  
  20402. CREATE PROCEDURE sp_MSinitdynamicsubscriber
  20403.     (@maxrows int, @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL)
  20404. as
  20405.     declare @retcode         smallint
  20406.     declare @procname        nvarchar(290)
  20407.     /*
  20408.     ** To public.
  20409.     */
  20410.     
  20411.     if (@tablenick is null)
  20412.         begin
  20413.         RAISERROR(14043, 16, -1, '@tablenick')
  20414.         return (1)
  20415.         end
  20416.     select @procname = view_sel_proc from sysmergearticles where
  20417.             pubid = @pubid and nickname = @tablenick
  20418.     exec @retcode = @procname @tablenick, @maxrows, @rowguid
  20419.     if @@ERROR<>0 or @retcode<>0 
  20420.         begin
  20421.             return (1)
  20422.         end    
  20423.     return (0)
  20424. go
  20425. exec dbo.sp_MS_marksystemobject sp_MSinitdynamicsubscriber
  20426. go
  20427. grant exec on dbo.sp_MSinitdynamicsubscriber to public
  20428.  
  20429.  
  20430. raiserror('Creating procedure sp_MSgetrowmetadata', 0,1)
  20431. GO
  20432.  
  20433. CREATE PROCEDURE sp_MSgetrowmetadata
  20434.     (@tablenick int,
  20435.      @rowguid uniqueidentifier,
  20436.      @generation int output,
  20437.      @type  tinyint output,
  20438.      @lineage varbinary(255) output,
  20439.      @colv varbinary(2048) output,
  20440.      @pubid uniqueidentifier = NULL)
  20441. as
  20442.     declare @retcode         smallint
  20443.     declare @saverr         int
  20444.     declare @rc             int
  20445.     declare @procname         nvarchar(270)
  20446.     
  20447.     /*
  20448.     ** To public.
  20449.     */
  20450.     
  20451.     
  20452.     if (@tablenick is null)
  20453.         begin
  20454.         RAISERROR(14043, 16, -1, '@tablenick')
  20455.         return (1)
  20456.         end
  20457.     if (@rowguid is null)
  20458.         begin
  20459.         RAISERROR(14043, 16, -1, '@rowguid')
  20460.         return (1)
  20461.         end
  20462.  
  20463.     set @type= 4
  20464.     set @generation= 0
  20465.     set @lineage= NULL
  20466.     set @colv= NULL
  20467.  
  20468.     select @procname= select_proc from sysmergearticles where nickname = @tablenick and pubid = @pubid
  20469.  
  20470.     -- check for row in base table
  20471.     exec @retcode= @procname @type=@type output, @rowguid=@rowguid
  20472.     if @@error <>0 or @retcode <> 0 
  20473.     begin
  20474.         return (1)
  20475.     end
  20476.  
  20477.     begin tran
  20478.     if (@type = 3)
  20479.     begin
  20480.         -- row is in base table; check whether it is in contents, too
  20481.         --
  20482.         -- serializable makes sure row does not go from tombstone to contents between 
  20483.         -- querying contents and tombstone, which would falsely result in type = missing
  20484.         select @type= 2,  @generation= generation, @lineage= lineage, @colv= colv1 from dbo.MSmerge_contents
  20485.             with (serializable)
  20486.             where tablenick = @tablenick and rowguid = @rowguid
  20487.     end
  20488.     else
  20489.     begin
  20490.         -- row is not in base table; either it is in tombstone, or it is missing
  20491.         set @type= 0
  20492.  
  20493.         select @type= type, @generation= generation, @lineage= lineage from dbo.MSmerge_tombstone where
  20494.             tablenick = @tablenick and rowguid = @rowguid
  20495.     end
  20496.     commit tran
  20497.     
  20498.     return (0)
  20499. go
  20500. exec dbo.sp_MS_marksystemobject sp_MSgetrowmetadata
  20501. go
  20502. grant exec on dbo.sp_MSgetrowmetadata to public
  20503. go
  20504.  
  20505.  
  20506. raiserror('Creating procedure sp_MSgetmetadatabatch', 0,1)
  20507. GO
  20508.  
  20509. CREATE PROCEDURE sp_MSgetmetadatabatch
  20510.     (@pubid uniqueidentifier,
  20511.      @tablenickarray varbinary(2000),
  20512.      @rowguidarray varbinary(8000)
  20513.     )
  20514. as
  20515.     declare @tablenick int
  20516.     declare @tablenicklast int
  20517.     declare @rowguid uniqueidentifier
  20518.     declare @generation int 
  20519.     declare @type  tinyint
  20520.     declare @lineage varbinary(255) 
  20521.     declare @colv varbinary(2048)
  20522.     declare @retcode         smallint
  20523.     declare @saverr         int
  20524.     declare @tnlength        int
  20525.     declare @tnoffset        int
  20526.     declare @guidoffset        int
  20527.     declare @procname         nvarchar(270)
  20528.  
  20529.     -- create temp table for returning results
  20530.     declare  @meta_batch TABLE (idx int identity, generation int, type  tinyint,
  20531.              lineage varbinary(255), colv varbinary(2048))
  20532.  
  20533.     /*
  20534.     ** To public.
  20535.     */
  20536.     
  20537.     if (@tablenickarray is null)
  20538.         begin
  20539.         RAISERROR(14043, 16, -1, '@tablenick')
  20540.         return (1)
  20541.         end
  20542.     if (@rowguidarray is null)
  20543.         begin
  20544.         RAISERROR(14043, 16, -1, '@rowguid')
  20545.         return (1)
  20546.         end
  20547.     
  20548.     set @tablenicklast = 0
  20549.     -- initialize offsets and length for walking through arrays
  20550.     set @tnoffset = 1
  20551.     set @guidoffset = 1
  20552.     set @tnlength = datalength(@tablenickarray)
  20553.  
  20554.  
  20555.     -- walk through arrays and populate temp table
  20556.     while (@tnoffset < @tnlength)
  20557.         begin
  20558.         set @tablenick = substring(@tablenickarray, @tnoffset, 4)
  20559.         set @rowguid = substring(@rowguidarray, @guidoffset, 16)
  20560.  
  20561.         -- instead of calling sp_MSgetrowmetadata, look it up ourselves might be faster
  20562.         
  20563.         --    exec @rc = sp_MSgetrowmetadata @tablenick, @rowguid,  @generation output,
  20564.          --    @type  output, @lineage output, @colv output, @pubid
  20565.         if @tablenick <> @tablenicklast
  20566.             begin
  20567.             select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid=@pubid
  20568.             set @tablenicklast = @tablenick
  20569.             end
  20570.  
  20571.         set @type= 4
  20572.         set @generation= 0
  20573.         set @lineage= NULL
  20574.         set @colv= NULL
  20575.  
  20576.         -- check for row in base table
  20577.         exec @retcode= @procname @type=@type output, @rowguid=@rowguid
  20578.         if @@error <>0 or @retcode <> 0 
  20579.         begin
  20580.             return (1)
  20581.         end
  20582.  
  20583.         begin tran
  20584.         if (@type = 3)
  20585.         begin
  20586.             -- row is in base table; check whether it is in contents, too
  20587.             --
  20588.             -- serializable makes sure row does not go from tombstone to contents between 
  20589.             -- querying contents and tombstone, which would falsely result in type = missing
  20590.             select @type= 2,  @generation= generation, @lineage= lineage, @colv= colv1 from dbo.MSmerge_contents
  20591.                 with (serializable)
  20592.                 where tablenick = @tablenick and rowguid = @rowguid
  20593.         end
  20594.         else
  20595.         begin
  20596.             -- row is not in base table; either it is in tombstone, or it is missing
  20597.             set @type= 0
  20598.  
  20599.             select @type= type, @generation= generation, @lineage= lineage from dbo.MSmerge_tombstone where
  20600.                 tablenick = @tablenick and rowguid = @rowguid
  20601.         end
  20602.         commit tran
  20603.  
  20604.  
  20605.          -- insert values into temp table
  20606.          insert into @meta_batch (generation, type, lineage, colv) values
  20607.              (@generation, @type, @lineage, @colv) 
  20608.  
  20609.          -- bump up offsets for next time through loop
  20610.          set @tnoffset = @tnoffset + 4
  20611.          set @guidoffset = @guidoffset + 16
  20612.         end
  20613.  
  20614.     -- select out our result set
  20615.     select generation, type, lineage, colv from @meta_batch order by idx
  20616.     
  20617.     return (0)
  20618. go
  20619. exec dbo.sp_MS_marksystemobject sp_MSgetmetadatabatch
  20620. go
  20621. grant exec on dbo.sp_MSgetmetadatabatch to public
  20622. go
  20623.  
  20624. raiserror('Creating procedure sp_MSsetrowmetadata', 0,1)
  20625. GO
  20626.  
  20627. CREATE PROCEDURE sp_MSsetrowmetadata
  20628.     (@tablenick int, @rowguid uniqueidentifier, @generation int,
  20629.      @lineage varbinary(255), @colv varbinary(2048), @type tinyint,
  20630.      @tombstone_rows_deleted int = NULL OUTPUT)
  20631. as
  20632.     declare @reason nvarchar(255), @retcode int
  20633.     
  20634.     /*
  20635.     ** Check to see if current publication has permission
  20636.     */
  20637.     if sessionproperty('replication_agent') = 0    
  20638.     begin
  20639.         exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  20640.         if @retcode<>0 or @@ERROR<>0 return (1)
  20641.     end
  20642.         
  20643.     if (@tablenick is null)
  20644.     begin
  20645.         RAISERROR(14043, 16, -1, '@tablenick')
  20646.         return (1)
  20647.     end
  20648.     if (@rowguid is null)
  20649.     begin
  20650.         RAISERROR(14043, 16, -1, '@rowguid')
  20651.         return (1)
  20652.     end
  20653.     if (@generation is null)
  20654.     begin
  20655.         RAISERROR(14043, 16, -1, '@generation')
  20656.         return (1)
  20657.     end
  20658.     if (@lineage is null)
  20659.     begin
  20660.         RAISERROR(14043, 16, -1, '@lineage')
  20661.         return (1)
  20662.     end
  20663.  
  20664.     if (@type=1 or @type=5 or @type=6)
  20665.     begin
  20666.         if @type = 5
  20667.         begin
  20668.             set @reason = formatmessage(20563) -- Out of partial range
  20669.             set @lineage = 0x00
  20670.         end
  20671.         else if @type = 6
  20672.         begin
  20673.             set @reason = formatmessage(20564) -- Deleted by system (e.g., to cope with dup key)
  20674.         end
  20675.         else
  20676.         begin
  20677.             set @reason = formatmessage(20562) -- Deleted by user
  20678.         end
  20679.         -- update or insert dbo.MSmerge_tombstone
  20680.         update dbo.MSmerge_tombstone set generation = @generation, lineage = @lineage, type = @type, reason = @reason
  20681.             where tablenick = @tablenick and rowguid = @rowguid
  20682.  
  20683.         if (@@rowcount = 0)
  20684.         begin
  20685.             insert into dbo.MSmerge_tombstone (rowguid, tablenick, type, generation, lineage, reason)
  20686.                 values (@rowguid, @tablenick, @type, @generation, @lineage, @reason)
  20687.  
  20688.             delete from dbo.MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid
  20689.         end
  20690.     end
  20691.     else
  20692.     begin
  20693.  
  20694.         if not exists (select rowguid from dbo.MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid)
  20695.         begin
  20696.             insert into dbo.MSmerge_contents (rowguid, tablenick, generation, lineage, colv1)
  20697.                 values (@rowguid, @tablenick, @generation, @lineage, @colv)
  20698.             delete from dbo.MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid
  20699.             select @tombstone_rows_deleted = @@rowcount
  20700.         end
  20701.         else
  20702.         begin
  20703.             -- update or insert to MSmerge_contents
  20704.             -- The following updates the generation to passed in value only if the 
  20705.             -- filter columns have not changed.
  20706.  
  20707.             -- If filter values have changed, update the generation to gen_cur for article - 
  20708.             -- This will allow a subsequent download to cleanup rows that don't belong at subscriber
  20709.             
  20710.             update dbo.MSmerge_contents 
  20711.             set generation = case when (isnull(partchangegen, -1) <> sma.gen_cur and isnull(joinchangegen, -1) <> sma.gen_cur) then @generation else sma.gen_cur end, 
  20712.                 lineage = @lineage, 
  20713.                 colv1 = case when datalength(@colv) < datalength(colv1) then colv1 else @colv end
  20714.             from dbo.MSmerge_contents mc, (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as sma
  20715.             where tablenick = @tablenick 
  20716.             and rowguid = @rowguid
  20717.             and mc.tablenick = sma.nickname
  20718.  
  20719.             if (@@rowcount = 0)
  20720.             begin
  20721.                 insert into dbo.MSmerge_contents (rowguid, tablenick, generation, lineage, colv1)
  20722.                     values (@rowguid, @tablenick, @generation, @lineage, @colv)
  20723.                 delete from dbo.MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid
  20724.                 select @tombstone_rows_deleted = @@rowcount
  20725.             end
  20726.         end
  20727.     end
  20728.  
  20729.     IF @@ERROR<>0 return (1) 
  20730.     return (0)
  20731. go
  20732. exec dbo.sp_MS_marksystemobject sp_MSsetrowmetadata
  20733. go
  20734. grant exec on dbo.sp_MSsetrowmetadata to public
  20735. go
  20736.  
  20737. raiserror('Creating procedure sp_MSinsertgenhistory', 0,1)
  20738. GO
  20739.  
  20740. CREATE PROCEDURE sp_MSinsertgenhistory
  20741.     (@guidsrc uniqueidentifier,
  20742.      @gen int output,
  20743.      @pubid uniqueidentifier,
  20744.      @pubid_ins uniqueidentifier = NULL,
  20745.      @nicknames varbinary(1000) = 0x0,
  20746.      @artnick int = NULL
  20747.     )
  20748. as
  20749.     /*
  20750.     ** Check to see if current publication has permission
  20751.     */
  20752.     declare @retcode int, @mynickname int, @newnicks varbinary(1000), @dt datetime
  20753.     
  20754.     if sessionproperty('replication_agent') = 0
  20755.     begin    
  20756.         exec @retcode=sp_MSreplcheck_connection
  20757.             @pubid = @pubid
  20758.         if @retcode<>0 or @@ERROR<>0 return (1)
  20759.     end
  20760.     
  20761.     if (@guidsrc is null)
  20762.     begin
  20763.         RAISERROR(14043, 16, -1, '@guidsrc')
  20764.         return (1)
  20765.     end
  20766.     
  20767.     -- having the login time in dbo.MSmerge_genhistory allows to associate the row with the merge process that inserted the row
  20768.     select @dt= login_time from master..sysprocesses where spid = @@spid
  20769.  
  20770.     -- Check for older in process generation
  20771.  
  20772.     select @gen = max(generation) from dbo.MSmerge_genhistory where guidsrc = @guidsrc
  20773.     if @gen is not null
  20774.     begin
  20775.         -- this generation was interrupted at a previous merge
  20776.         -- next statement makes sure that gen does no longer look interrupted to another process
  20777.         update dbo.MSmerge_genhistory set coldate= @dt where guidsrc = @guidsrc
  20778.  
  20779.         -- if @@rowcount = 0, another process removed the interrupted gen just before the previous update statement
  20780.         if @@rowcount > 0
  20781.         begin
  20782.             return (0)
  20783.         end
  20784.     end
  20785.  
  20786.     exec dbo.sp_MSgetreplnick @nickname = @mynickname out
  20787.     if @@ERROR<>0 return (1)
  20788.  
  20789.     -- Append guard byte if it is needed
  20790.     if @nicknames = 0x0 and (@mynickname % 256 = 0)
  20791.         set @newnicks = convert(binary(4), @mynickname) + 0x01
  20792.     else
  20793.         set @newnicks = convert(binary(4), @mynickname) + @nicknames
  20794.         
  20795.     begin tran
  20796.     save tran sp_MSinsertgenhistory
  20797.     
  20798.     select @gen = COALESCE(1 + max(generation), 1) from dbo.MSmerge_genhistory (updlock)
  20799.  
  20800.     if (@gen is NULL)
  20801.         select @gen = 1
  20802.     
  20803.     insert into dbo.MSmerge_genhistory (guidsrc, pubid, guidlocal, generation, art_nick, nicknames, coldate) 
  20804.         values (@guidsrc, @pubid_ins, '00000000-0000-0000-0000-000000000000', @gen, @artnick, @newnicks, @dt)
  20805.  
  20806.     if @@error<>0 goto Failure
  20807.         
  20808.     commit tran
  20809.     return (0)
  20810. Failure:
  20811.     rollback tran sp_MSinsertgenhistory
  20812.     commit tran
  20813.     RAISERROR(15001, 16, -1, 'MSmerge_genhistory')
  20814.     return (1)
  20815. go
  20816. exec dbo.sp_MS_marksystemobject sp_MSinsertgenhistory
  20817. go
  20818. grant exec on dbo.sp_MSinsertgenhistory to public
  20819.  
  20820. raiserror('Creating procedure sp_MSupdategenhistory', 0,1)
  20821. GO
  20822.  
  20823. CREATE PROCEDURE sp_MSupdategenhistory
  20824.     (@guidsrc uniqueidentifier, @pubid uniqueidentifier, @gen int, @art_nick int = NULL)
  20825. as
  20826.     declare @guidlocal uniqueidentifier
  20827.     
  20828.     /*
  20829.     ** Check to see if current publication has permission
  20830.     */
  20831.     declare @retcode int
  20832.  
  20833.     if sessionproperty('replication_agent') = 0
  20834.     begin
  20835.         exec @retcode=sp_MSreplcheck_connection
  20836.             @pubid = @pubid
  20837.         if @retcode<>0 or @@ERROR<>0 return (1)
  20838.     end
  20839.     
  20840.     if (@guidsrc is null)
  20841.     begin
  20842.         RAISERROR(14043, 16, -1, '@guidsrc')
  20843.         return (1)
  20844.     end
  20845.         
  20846.     if @art_nick = 0 set @art_nick = NULL
  20847.     
  20848.     set @guidlocal = newid()
  20849.     begin tran
  20850.     save tran sp_MSupdategenhistory
  20851.     if exists (select * from dbo.MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen)
  20852.     begin
  20853.         create table #gentable (generation int)
  20854.  
  20855.         insert into #gentable select generation from dbo.MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen
  20856.  
  20857.         update mc set mc.generation= @gen from dbo.MSmerge_contents as mc inner join #gentable as g 
  20858.             on (mc.generation=g.generation) 
  20859.         if @@ERROR <> 0 goto FAILURE
  20860.  
  20861.         update mt set mt.generation= @gen from dbo.MSmerge_tombstone as mt inner join #gentable as g 
  20862.             on (mt.generation=g.generation) 
  20863.         if @@ERROR <> 0 goto FAILURE
  20864.         
  20865.         declare @cmd nvarchar(200)
  20866.         declare @bi_objid int
  20867.         set @bi_objid= (select top 1 before_image_objid from sysmergearticles where nickname = @art_nick)
  20868.         if @bi_objid is not null
  20869.         begin
  20870.             set @cmd= 'update bi set bi.generation= @gen from dbo.' + object_name(@bi_objid) + ' as bi inner join #gentable as g
  20871.                 on (bi.generation = g.generation)'
  20872.             exec dbo.sp_executesql @cmd, N'@gen int', @gen= @gen
  20873.             if @@ERROR <> 0 goto FAILURE
  20874.         end
  20875.  
  20876.         delete from dbo.MSmerge_genhistory where guidsrc = @guidsrc and generation < @gen
  20877.         
  20878.         if @@ERROR <> 0 goto FAILURE
  20879.  
  20880.         drop table #gentable
  20881.     end
  20882.     if exists (select * from dbo.MSmerge_genhistory where guidsrc = @guidsrc)
  20883.         update dbo.MSmerge_genhistory set   guidlocal= @guidlocal, 
  20884.                                             art_nick = case when isnull(@art_nick,0) <> 0 then @art_nick else art_nick end, 
  20885.                                             coldate= getdate() 
  20886.                                             where guidsrc = @guidsrc 
  20887.     else
  20888.     begin
  20889.         declare @mynickname int
  20890.         declare @nickbin varbinary(255)
  20891.  
  20892.         exec dbo.sp_MSgetreplnick @nickname = @mynickname out
  20893.         if @@ERROR<>0 goto FAILURE
  20894.  
  20895.         -- Append guard byte if it is needed
  20896.         if @mynickname % 256 = 0
  20897.             set @nickbin  = convert(binary(4), @mynickname) + 0x01
  20898.         else
  20899.             set @nickbin  = convert(binary(4), @mynickname)
  20900.  
  20901.         insert into dbo.MSmerge_genhistory (guidsrc, guidlocal, generation, art_nick, nicknames, coldate) values
  20902.             (@guidsrc, @guidlocal, @gen, @art_nick, @nickbin , getdate())
  20903.  
  20904.  
  20905.     end
  20906.  
  20907.     commit
  20908.  
  20909.     -- Now that we have closed a generation that was open, we might be ready to
  20910.     -- cleanup metadata or something like that.
  20911.     exec @retcode = sp_MSquiescecheck                    
  20912.     
  20913.     return (0)
  20914.     
  20915. FAILURE:
  20916.     rollback tran sp_MSupdategenhistory
  20917.     commit tran
  20918.     return(1)
  20919. go
  20920. exec dbo.sp_MS_marksystemobject sp_MSupdategenhistory
  20921. go
  20922. grant exec on dbo.sp_MSupdategenhistory to public
  20923. go
  20924.  
  20925. raiserror('Creating procedure sp_MSlocalizeinterruptedgenerations', 0,1)
  20926. GO
  20927.  
  20928. CREATE PROCEDURE sp_MSlocalizeinterruptedgenerations @localize_zeroartnick_generations bit=0
  20929. -- this proc loops over interrupted generations 
  20930. -- and transfers those changes that arrived before the interrupt to a new local generation
  20931. as
  20932. begin
  20933.  
  20934.     declare @new_guidsrc uniqueidentifier
  20935.  
  20936.     if @localize_zeroartnick_generations = 0
  20937.         update dbo.MSmerge_genhistory set @new_guidsrc = guidsrc = newid(), guidlocal = @new_guidsrc, coldate = getdate()
  20938.         where guidlocal = '00000000-0000-0000-0000-000000000000'  -- incomplete gen
  20939.         and generation not in (select gen_cur from sysmergearticles)  -- not a local incomplete gen
  20940.         and coldate not in (select login_time from master..sysprocesses)  -- not a gen that currently receives replica updates from another db
  20941.         and isnull(art_nick, 0) <> 0        -- we don't localize generations with art_nick = 0 or NULL.
  20942.     else
  20943.         update dbo.MSmerge_genhistory set @new_guidsrc = guidsrc = newid(), guidlocal = @new_guidsrc, coldate = getdate()
  20944.         where guidlocal = '00000000-0000-0000-0000-000000000000'  -- incomplete gen
  20945.         and generation not in (select gen_cur from sysmergearticles)  -- not a local incomplete gen
  20946.         and coldate not in (select login_time from master..sysprocesses)  -- not a gen that currently receives replica updates from another db
  20947.     
  20948.     if @@error <> 0
  20949.         return 1
  20950.     else
  20951.         return 0
  20952. end
  20953. go
  20954. exec dbo.sp_MS_marksystemobject sp_MSlocalizeinterruptedgenerations
  20955. go
  20956. grant exec on dbo.sp_MSlocalizeinterruptedgenerations to public
  20957. go
  20958.  
  20959. raiserror('Creating procedure sp_MSenumschemachange', 0,1)
  20960. GO
  20961.  
  20962. CREATE PROCEDURE sp_MSenumschemachange(
  20963.     @pubid                  uniqueidentifier,
  20964.     @schemaversion          int,
  20965.     @compatibility_level int = 7000000,
  20966.     @AlterTableOnly         bit = 0
  20967.     )
  20968. as    
  20969.     set nocount on
  20970.     declare @retcode int
  20971.  
  20972.     select @retcode = 0
  20973.  
  20974.     -- Delegate call to the appropriate sp that
  20975.     -- handles the given compatibility-level  
  20976.     if @compatibility_level > 7000200 --this value standing for 70SP2
  20977.     begin
  20978.         exec @retcode = sp_MSenumschemachange_80 @pubid = @pubid, 
  20979.                                                  @AlterTableOnly = @AlterTableOnly,
  20980.                                                  @schemaversion = @schemaversion
  20981.     end
  20982.     else
  20983.     begin
  20984.         exec @retcode = sp_MSenumschemachange_70 @pubid = @pubid,
  20985.                                                  @AlterTableOnly = @AlterTableOnly,
  20986.                                                  @schemaversion = @schemaversion,
  20987.                                                  @compatibility_level=@compatibility_level
  20988.     end
  20989.  
  20990.     return @retcode
  20991. go
  20992. exec dbo.sp_MS_marksystemobject sp_MSenumschemachange
  20993. go
  20994. grant exec on dbo.sp_MSenumschemachange to public
  20995. go
  20996.  
  20997. raiserror('Creating procedure sp_MSenumschemachange_70', 0,1)
  20998. GO
  20999.  
  21000. CREATE PROCEDURE sp_MSenumschemachange_70(
  21001.     @pubid                         uniqueidentifier,
  21002.     @AlterTableOnly                int,
  21003.     @schemaversion                 int,
  21004.     @compatibility_level         int
  21005.     )
  21006. as
  21007.  
  21008.     /*
  21009.     ** To public
  21010.     */
  21011.     
  21012.     if (@schemaversion is null)
  21013.         begin
  21014.         RAISERROR(14043, 16, -1, '@schemaversion')
  21015.         return (1)
  21016.         end
  21017.  
  21018.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  21019.         begin
  21020.         RAISERROR(20054 , 16, -1)
  21021.         return (1)
  21022.         end
  21023.  
  21024.     create table #temp_table_sp_MSenumschemachange_70
  21025.         (pubid uniqueidentifier NULL, 
  21026.          artid uniqueidentifier NULL,
  21027.          schemaversion int NULL,
  21028.          schemaguid uniqueidentifier NULL,
  21029.          schematype int NULL,
  21030.          schematext nvarchar(2000) collate database_default null)
  21031.  
  21032.     /* handle the case of reinitall */
  21033.     if exists (select pubid from sysmergeschemachange where schemaversion > @schemaversion 
  21034.              and pubid = @pubid and schematype = 12)
  21035.         select @schemaversion = 0
  21036.  
  21037.     /*
  21038.     ** For 70 RTM and SP1, we want to filter out type 9 (retention propagation) and 16 (metadata cleanup)
  21039.     ** and 5 ( last rec generation ) and 6 (last sent generation)
  21040.     ** which they do not support. SP2 subscriber will be passing in 7000200, which gets understands
  21041.     ** these schema types
  21042.     */
  21043.     insert into #temp_table_sp_MSenumschemachange_70
  21044.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21045.           from sysmergeschemachange where schemaversion > @schemaversion 
  21046.                  and pubid = @pubid
  21047.                 and ((@compatibility_level=7000000 and schematype in (-1, 1, 2, 3, 4, 7, 8, 10, 15, 20))
  21048.                     or (@compatibility_level=7000200 and 
  21049.                         ((schematype in (-1, 1, 2, 3, 4, 7, 8, 9, 10, 12, 15, 16, 20,66)) 
  21050.                             or schematype in (5, 6) and @schemaversion = 0)))
  21051.         order by schemaversion         
  21052.         
  21053.     /* for SP2 downlevel subscribers who do not understand type 12 (reinit-all) at provider level, but do
  21054.     ** at reconcile level, change it to type = 7 (directory) to be no-op.
  21055.     */
  21056.     if @compatibility_level=7000200
  21057.         update #temp_table_sp_MSenumschemachange_70 set schematype=7 where schematype = 12
  21058.  
  21059.     select  * from #temp_table_sp_MSenumschemachange_70
  21060.     drop table #temp_table_sp_MSenumschemachange_70
  21061.     
  21062.     return (0)
  21063. go
  21064. exec dbo.sp_MS_marksystemobject sp_MSenumschemachange_70
  21065. go
  21066. grant exec on dbo.sp_MSenumschemachange_70 to public
  21067. go
  21068.  
  21069.  
  21070. raiserror('Creating procedure sp_MSenumschemachange_80', 0,1)
  21071. GO
  21072.  
  21073. CREATE PROCEDURE sp_MSenumschemachange_80(
  21074.     @pubid                    uniqueidentifier,
  21075.     @AlterTableOnly                    int,
  21076.     @schemaversion            int
  21077.     )
  21078. as
  21079.     set nocount on
  21080.     /*
  21081.     ** To public
  21082.     */
  21083.     declare    @alter_table_type        int
  21084.     declare @reinit_all_type         int
  21085.     declare @reinit_all_upload_type int
  21086.     declare @schemaversion_of_snapshottrailer int
  21087.     
  21088.     select @reinit_all_type = 12
  21089.     select @alter_table_type = 11
  21090.     select @reinit_all_upload_type = 14
  21091.     
  21092.     if (@schemaversion is null)
  21093.         begin
  21094.         RAISERROR(14043, 16, -1, '@schemaversion')
  21095.         return (1)
  21096.         end
  21097.  
  21098.         --    @schema_needed = 0 - only send back reinitall command, if any 
  21099.         --  @schema_needed = 1 - normal enumeration
  21100.         --  @schema_needed = 2 - only send back alter-table command, if any
  21101.         --  @schema_needed = 3 - only send back reinitall-with-upload command, if any.
  21102.  
  21103.     if (@AlterTableOnly = 1)
  21104.         begin
  21105.             select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21106.                 from sysmergeschemachange where pubid=@pubid and schemaversion > @schemaversion and schematype = @alter_table_type
  21107.             return (0)            
  21108.         end
  21109.         
  21110.     if exists (select * from sysmergeschemachange where 
  21111.         pubid=@pubid and ((schemaversion > @schemaversion and schematype = @reinit_all_type)
  21112.         or (schemaversion > @schemaversion and schematype = @reinit_all_upload_type)))
  21113.         begin
  21114.             select @schemaversion=0
  21115.         end
  21116.  
  21117.     -- If subscriber missed a preparecleanup and a completecleanup they must be reinitialized
  21118.     
  21119.     if exists (select * from sysmergeschemachange where 
  21120.         pubid=@pubid and schemaversion > @schemaversion and schematype = 17) and
  21121.         exists (select * from sysmergeschemachange where 
  21122.         pubid=@pubid and schemaversion > @schemaversion and schematype = 19)         
  21123.         begin
  21124.             set @schemaversion=0
  21125.         end
  21126.         
  21127.     if (@schemaversion > 0) 
  21128.     begin
  21129.         -- Subscriber has already received the snapshot so filter out 
  21130.         -- the pre/post-snapshot commands. 
  21131.         -- Also filter out the schemtypes for the setlastsentgen (5) and setlastrecgen (6)
  21132.         -- This ensures that the subscriber does not apply these schema changes when 
  21133.         -- it applies incremental schema - ie the perf optimization that is implemented 
  21134.         -- by setting last sent/rec generation should be done only for brand new subscriptions.
  21135.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21136.           from sysmergeschemachange where schemaversion > @schemaversion  
  21137.            and pubid = @pubid
  21138.            and schematype not in (40, 45, 50, 51, 52, 53, 54, 55, 56, 25, 5, 6)
  21139.       order by schemaversion 
  21140.     end
  21141.     Else 
  21142.     begin
  21143.         -- Subscriber requires a snapshot, so carefully sequence the 
  21144.         -- pre/post-snapshot commands around the snapshot boundary
  21145.  
  21146.         create table #schemachanges 
  21147.         (   
  21148.             pubid           uniqueidentifier  NOT NULL,
  21149.             artid           uniqueidentifier  NULL,
  21150.             schemaversion   int               NOT NULL,
  21151.             schemaguid      uniqueidentifier  NOT NULL,
  21152.             schematype      int               NOT NULL,
  21153.             schematext      nvarchar(2000)    collate database_default not null,
  21154.             seqno           int identity      NOT NULL
  21155.         )
  21156.         
  21157.         truncate table #schemachanges
  21158.         -- Insert snapshot header 
  21159.  
  21160.         -- Header begins
  21161.         insert into #schemachanges
  21162.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21163.           from sysmergeschemachange where schemaversion > @schemaversion 
  21164.            and pubid = @pubid
  21165.            and schematype = 50
  21166.  
  21167.         -- Header content
  21168.         insert into #schemachanges
  21169.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21170.           from sysmergeschemachange where schemaversion > @schemaversion 
  21171.            and pubid = @pubid
  21172.            and schematype in (25, 53, 54, 55, 56, 57, 58) 
  21173.         order by schemaversion 
  21174.  
  21175.         -- Header ends
  21176.         insert into #schemachanges
  21177.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21178.           from sysmergeschemachange where schemaversion > @schemaversion 
  21179.            and pubid = @pubid
  21180.            and schematype = 51 
  21181.  
  21182.         -- End of snapshot header 
  21183.         -- Insert pre command
  21184.         insert into #schemachanges
  21185.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21186.           from sysmergeschemachange where schemaversion > @schemaversion 
  21187.            and pubid = @pubid
  21188.            and schematype = 40 
  21189.  
  21190.         -- Exclude pre-post, but include snapshot only commands
  21191.         insert into #schemachanges
  21192.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21193.           from sysmergeschemachange where schemaversion > @schemaversion 
  21194.            and pubid = @pubid
  21195.            and schematype in (2, 3, 4, 20, 7, 60, 61, 62, 63, 64)
  21196.          order by schemaversion 
  21197.  
  21198.         -- Dynamic BCP commands
  21199.         insert into #schemachanges
  21200.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21201.           from sysmergeschemachange where schemaversion > @schemaversion 
  21202.            and pubid = @pubid
  21203.            and schematype in (131, 132)
  21204.          order by schemaversion         
  21205.         
  21206.         -- DRI/Trg/XPROP
  21207.         insert into #schemachanges
  21208.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21209.           from sysmergeschemachange where schemaversion > @schemaversion 
  21210.            and pubid = @pubid
  21211.            and schematype in (10, 15, 65)
  21212.          order by schemaversion         
  21213.  
  21214.         -- Insert post command
  21215.         insert into #schemachanges
  21216.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21217.           from sysmergeschemachange where schemaversion > @schemaversion 
  21218.            and pubid = @pubid
  21219.            and schematype = 45 
  21220.  
  21221.         -- Insert snapshot trailer
  21222.         insert into #schemachanges
  21223.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21224.           from sysmergeschemachange where schemaversion > @schemaversion 
  21225.            and pubid = @pubid
  21226.            and schematype = 52 
  21227.         
  21228.         -- Insert other schema changes
  21229.         insert into #schemachanges 
  21230.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21231.           from sysmergeschemachange where schemaversion > @schemaversion 
  21232.            and schematype not in (2, 3, 4, 10, 15, 20, 7, 40, 45, 60)
  21233.            and schematype not in (61, 62, 63, 64, 65)
  21234.            and schematype not in (25, 50, 51, 52, 53, 54, 55, 56, 57, 58)
  21235.            and schematype not in (131, 132) -- dynamic bcp commands
  21236.            and schematype not in (46, 11, 13) -- The on-demand script and schema replication commands should not be enumerated unless 
  21237.                                       -- we have made sure that it was posted after the current snapshot.
  21238.            and pubid = @pubid
  21239.          order by schemaversion                   
  21240.  
  21241.         -- get the schemaversion of the snapshot trailer row
  21242.         select @schemaversion_of_snapshottrailer = schemaversion from sysmergeschemachange 
  21243.             where schemaversion > @schemaversion 
  21244.             and pubid = @pubid
  21245.             and schematype = 52 
  21246.  
  21247.         if (@schemaversion_of_snapshottrailer is not null)
  21248.         begin
  21249.             -- insert schema changes for on-demand script and schema replication commands which have schemaversion greater than
  21250.             -- schemaversion of the snapshot trailer row
  21251.             insert into #schemachanges 
  21252.             select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21253.             from sysmergeschemachange where schemaversion > @schemaversion_of_snapshottrailer 
  21254.             and schematype in (46, 11, 13) -- The on-demand script and schema replication commands only.
  21255.             and pubid = @pubid
  21256.             order by schemaversion
  21257.         end
  21258.             
  21259.         declare @endofsnapshot int
  21260.         select @endofsnapshot = min(seqno) from #schemachanges 
  21261.         where schematype = 52
  21262.         delete #schemachanges where seqno > @endofsnapshot
  21263.             and (schematype in (2, 3, 4, 10, 15, 20, 7, 40, 45, 65) or 
  21264.             schematype in (25, 50, 51, 52, 53, 54, 55, 56, 57, 58))
  21265.  
  21266.         --only list the last reinitall command 
  21267.         delete schemachanges1 from #schemachanges schemachanges1,#schemachanges schemachanges2 
  21268.             where schemachanges1.pubid=@pubid and schemachanges1.schematype=12 and 
  21269.                   schemachanges2.pubid=@pubid and schemachanges2.schematype=12 and
  21270.                   schemachanges1.schemaversion<schemachanges2.schemaversion
  21271.         
  21272.         --only list the last reinitall-with-upload command 
  21273.         delete schemachanges1 from #schemachanges schemachanges1, #schemachanges schemachanges2 
  21274.             where schemachanges1.pubid=@pubid and schemachanges1.schematype=14 and 
  21275.                   schemachanges2.pubid=@pubid and schemachanges2.schematype=14 and
  21276.                   schemachanges1.schemaversion<schemachanges2.schemaversion
  21277.  
  21278.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  21279.           from #schemachanges order by seqno
  21280.  
  21281.         drop table #schemachanges
  21282.     end
  21283.  
  21284.     return (0)
  21285. go
  21286. exec dbo.sp_MS_marksystemobject sp_MSenumschemachange_80
  21287. go
  21288. grant exec on dbo.sp_MSenumschemachange_80 to public
  21289. go
  21290.  
  21291. raiserror('Creating procedure sp_MSupdateschemachange', 0,1)
  21292. GO
  21293.  
  21294. CREATE PROCEDURE sp_MSupdateschemachange(
  21295.     @pubid            uniqueidentifier,
  21296.     @artid            uniqueidentifier = NULL, /* Can be NULL for directory commands */
  21297.     @schemaversion     int,
  21298.     @schemaguid        uniqueidentifier,
  21299.     @schematype        int,
  21300.     @schematext        nvarchar(2000)
  21301.     )
  21302. as
  21303.     /*
  21304.     ** Check to see if current publication has permission
  21305.     */
  21306.     declare @retcode int
  21307.  
  21308.     if sessionproperty('replication_agent') = 0
  21309.     begin
  21310.         exec @retcode=sp_MSreplcheck_connection
  21311.             @pubid = @pubid
  21312.         if @retcode<>0 or @@ERROR<>0 return (1)
  21313.     end
  21314.     
  21315.     /* Parameter validation */
  21316.     if (@schemaversion is null)
  21317.         begin
  21318.         RAISERROR(14043, 16, -1, '@schemaversion')
  21319.         return (1)
  21320.         end
  21321.  
  21322.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  21323.         begin
  21324.         RAISERROR(20054 , 16, -1)
  21325.         return (1)
  21326.         end
  21327.  
  21328.     update sysmergeschemachange set schematext = @schematext, schematype = @schematype
  21329.         where pubid = @pubid and schemaversion = @schemaversion
  21330.     if @@error <> 0        
  21331.         begin
  21332.             RAISERROR(20054 , 16, -1)
  21333.             return (1)
  21334.         end        
  21335.     return (0)
  21336. go
  21337. exec dbo.sp_MS_marksystemobject sp_MSupdateschemachange
  21338. go
  21339. grant exec on dbo.sp_MSupdateschemachange to public
  21340. go
  21341.  
  21342. raiserror('Creating procedure sp_MSremove_mergereplcommand', 0,1)
  21343. GO
  21344.  
  21345. /* Remove an article command of a specific tyep from sysmergeschemachange- Used by snapshot */
  21346. CREATE PROCEDURE sp_MSremove_mergereplcommand (
  21347.     @publication        sysname,
  21348.     @article            sysname,
  21349.     @schematype         int
  21350.     ) AS
  21351.     set nocount on
  21352.     declare @pubid                uniqueidentifier
  21353.     declare @artid                uniqueidentifier
  21354.     declare @retcode            int    
  21355.  
  21356.     exec @retcode=sp_MSreplcheck_publish
  21357.     if @retcode<>0 or @@ERROR<>0 return (1)
  21358.     
  21359.     if @publication IS NULL
  21360.     begin
  21361.         raiserror (14003, 16, -1)
  21362.         return (1)
  21363.     end
  21364.     
  21365.     if @article IS NULL
  21366.     begin
  21367.         raiserror (20045, 16, -1)
  21368.         return (1)
  21369.     end
  21370.  
  21371.     select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  21372.     select @artid = artid FROM sysmergearticles WHERE name = @article and pubid=@pubid
  21373.  
  21374.     delete sysmergeschemachange where pubid = @pubid
  21375.                                   and artid = @artid
  21376.                              and schematype = @schematype
  21377.  
  21378. GO
  21379.  
  21380. exec dbo.sp_MS_marksystemobject sp_MSremove_mergereplcommand
  21381. go
  21382. grant exec on dbo.sp_MSremove_mergereplcommand to public
  21383. go
  21384.  
  21385. raiserror('Creating procedure sp_MSadd_mergereplcommand', 0,1)
  21386. GO
  21387.  
  21388. /* Add the replication command to the database - Used by snapshot */
  21389. CREATE PROCEDURE sp_MSadd_mergereplcommand (
  21390.     @publication        sysname,
  21391.     @article            sysname = NULL,
  21392.     @schematype            int,
  21393.     @schematext            nvarchar(2000)
  21394.     ) AS
  21395.     declare @schemaguid            uniqueidentifier
  21396.     declare @schemaversion         int
  21397.     declare @retcode             int
  21398.     declare @pubid                uniqueidentifier
  21399.     declare @artid                uniqueidentifier
  21400.     
  21401.     /*
  21402.     ** Publish permission check
  21403.     */
  21404.     exec @retcode=sp_MSreplcheck_publish
  21405.     if @retcode<>0 or @@ERROR<>0 return (1)
  21406.     
  21407.     if @publication IS NULL
  21408.         BEGIN
  21409.             RAISERROR (14003, 16, -1)
  21410.             RETURN (1)
  21411.         END
  21412.  
  21413.     select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  21414.     select @artid = artid FROM sysmergeextendedarticlesview WHERE name = @article and pubid = @pubid
  21415.     /* 
  21416.     ** For certain system tables that are bcped out such as MSmerge_contents 
  21417.     ** and dbo.MSmerge_tombstone use the article name as sysobjects.name and get
  21418.     ** sysobjects.id as the artid
  21419.     */
  21420.     if (@artid IS NULL) AND (@schematype <> 7)
  21421.         begin
  21422.             declare @binguid binary(16)
  21423.             set @binguid = OBJECT_ID(@article)
  21424.             set @artid = convert(uniqueidentifier, @binguid)
  21425.         end
  21426.  
  21427.     if exists (select *    from sysmergeschemachange
  21428.             where pubid = @pubid 
  21429.             AND artid = @artid
  21430.             AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4)) )
  21431.         begin
  21432.             /* Select the existing schema guid */
  21433.             select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange
  21434.                 where pubid = @pubid 
  21435.                 AND artid = @artid
  21436.                 AND (schematype = @schematype or @schematype in (3,4) and schematype in (3,4))
  21437.  
  21438.  
  21439.             /* For directory commands, delete the previous directory before the update */
  21440.             if (@schematype = 7)
  21441.                 begin
  21442.  
  21443.                     /* Remove the alternate directory command, pre/post 
  21444.                     ** commands, and snapshot header commands from the 
  21445.                     ** sysmergeschemachange table
  21446.                     */                     
  21447.                     delete sysmergeschemachange
  21448.                      where pubid = @pubid 
  21449.                        AND schematype in (25, 40, 45, 50, 51, 52, 53, 54, 55, 56, 57, 58)
  21450.  
  21451.                 end
  21452.  
  21453.             /*
  21454.             ** Update the schema change version
  21455.             */
  21456.             exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, 
  21457.                 @schemaguid, @schematype, @schematext
  21458.             if @@error <> 0    or @retcode <> 0
  21459.                 begin
  21460.                 RAISERROR(20054 , 16, -1)
  21461.                 return (1)
  21462.             end
  21463.         end
  21464.     else        
  21465.         begin
  21466.             /* Insert the schema change */
  21467.             select @schemaversion = schemaversion from sysmergeschemachange
  21468.             if (@schemaversion is NULL)
  21469.                 set @schemaversion = 1
  21470.             else
  21471.                 select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  21472.  
  21473.             /* update the schema version and schemaguid in MSmerge_replinfo */        
  21474.             declare @srvid         int
  21475.             declare @repid         uniqueidentifier
  21476.             declare @MSmerge_replinfoschemaversion     int
  21477.             declare @MSmerge_replinfoschemaguid     uniqueidentifier
  21478.  
  21479.             select @srvid = 0
  21480.             select  @repid = repid from MSmerge_replinfo 
  21481.                 where repid in (select subid from sysmergesubscriptions
  21482.                     where srvid = @srvid and db_name = DB_NAME() and pubid = @pubid)
  21483.  
  21484.             select @MSmerge_replinfoschemaversion = schemaversion, @MSmerge_replinfoschemaguid = schemaguid
  21485.                     from dbo.MSmerge_replinfo where repid = @repid 
  21486.  
  21487.             /* 
  21488.             ** If the schema version matches the MSmerge_replinfo.schemaversion and the schema_type = 52 (snapshot trailer), 
  21489.             ** then reuse the MSmerge_replinfo.schema_guid. Otherwise generate a new guid.
  21490.             */
  21491.             if @MSmerge_replinfoschemaversion is NOT NULL and @schemaversion = @MSmerge_replinfoschemaversion and @schematype = 52
  21492.                 begin
  21493.                     set @schemaguid = @MSmerge_replinfoschemaguid
  21494.                 end
  21495.             else
  21496.                 begin
  21497.                     set @schemaguid = newid()
  21498.                 end
  21499.                 
  21500.             exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, 
  21501.                 @schemaguid, @schematype, @schematext
  21502.             if @@error <> 0    or @retcode <> 0
  21503.                 begin
  21504.                     RAISERROR(20054 , 16, -1)
  21505.                     return (1)
  21506.                 end
  21507.         end
  21508.     if (@schematype = 7)
  21509.         begin
  21510.             update sysmergesubscriptions set last_validated=getdate() where pubid=@pubid and subid=@pubid
  21511.             IF @@ERROR <> 0
  21512.             begin
  21513.                 RAISERROR(20054 , 16, -1)
  21514.                 RETURN (1)
  21515.             end
  21516.         end        
  21517.     return (0)
  21518. go
  21519. exec dbo.sp_MS_marksystemobject sp_MSadd_mergereplcommand 
  21520. go
  21521. grant exec on dbo.sp_MSadd_mergereplcommand to public
  21522. go
  21523. raiserror('Creating procedure sp_MSsetreplicainfo', 0,1)
  21524. GO
  21525.  
  21526. CREATE PROCEDURE sp_MSsetreplicainfo
  21527.     (@publisher            sysname,
  21528.      @publisher_db        sysname,
  21529.      @publication         sysname,
  21530.      @datasource_type    int = 0,             /* 0 = SQL Server, 1 = DSN, 2 = Jet */
  21531.      @server_name        sysname    = NULL, /* Server Name */
  21532.      @db_name            sysname = NULL, /* Database Name */
  21533.      @datasource_path    nvarchar(255) = NULL,/* Datasource path - JET MDB file path etc */
  21534.      @nickname     int = NULL,
  21535.      @schemaversion int = NULL,
  21536.      @subid    uniqueidentifier = NULL)
  21537. as
  21538.     declare     @pubid         uniqueidentifier
  21539.     declare     @repid         uniqueidentifier
  21540.     declare        @srvid        int
  21541.     declare        @retcode    int
  21542.  
  21543.     /*
  21544.     ** NOTE -- WORKAROUND ODBC PROBLEM
  21545.     */
  21546.     select @publisher_db = RTRIM(@publisher_db)
  21547.     select @db_name = RTRIM(@db_name)
  21548.     
  21549.     /*
  21550.     ** Subscriber permission check
  21551.     */
  21552.     if UPPER(@@servername) = UPPER(@publisher) and db_name() = @publisher_db
  21553.     begin
  21554.         if sessionproperty('replication_agent') = 0
  21555.         begin
  21556.             exec @retcode=sp_MSreplcheck_connection
  21557.                 @publication = @publication
  21558.             if @retcode<>0 or @@ERROR<>0 return (1)
  21559.         end
  21560.     end
  21561.     else
  21562.     begin
  21563.         exec @retcode=sp_MSreplcheck_subscribe
  21564.         if @retcode<>0 or @@ERROR<>0 return (1)
  21565.     end
  21566.     
  21567.     /*
  21568.     ** Parameter Check:  @publication.
  21569.     ** Make sure that the publication exists.
  21570.     */
  21571.     if (@publication is null)
  21572.         begin
  21573.         RAISERROR(14043, 16, -1, '@publication')
  21574.         return (1)
  21575.         end
  21576.  
  21577.     if (@server_name is NULL)
  21578.         SET @server_name = @@SERVERNAME
  21579.  
  21580.     if (@db_name is NULL)
  21581.         set @db_name = db_name()
  21582.         
  21583.     SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@server_name) collate database_default
  21584.        IF @@ERROR <> 0 or @srvid IS NULL
  21585.            BEGIN
  21586.             RAISERROR(20021, 16, -1)
  21587.              RETURN (1)
  21588.         END
  21589.  
  21590.     select @pubid = pubid from sysmergepublications 
  21591.         where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  21592.     if (@pubid is null)
  21593.         begin
  21594.             RAISERROR (20026, 11, -1, @publication)
  21595.             return (1)
  21596.         end
  21597.  
  21598.     if (@datasource_type = 0)
  21599.         begin
  21600.             /*
  21601.             ** SQL Server
  21602.             */
  21603.             SELECT @repid = subid FROM sysmergesubscriptions
  21604.                 WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid
  21605.             update sysmergesubscriptions set validation_level = 0, resync_gen=-1 where subid=@repid
  21606.         END
  21607.     ELSE IF (@datasource_type = 4) or (@datasource_type = 5)
  21608.         BEGIN
  21609.             /* 
  21610.             ** Exchange or Oracle 
  21611.             */
  21612.             SELECT @repid = subid FROM sysmergesubscriptions
  21613.                 WHERE srvid = @srvid and pubid = @pubid
  21614.         END
  21615.     ELSE
  21616.         BEGIN
  21617.             /*
  21618.             ** Jet
  21619.             */
  21620.             SELECT @repid = subid FROM sysmergesubscriptions
  21621.                 WHERE datasource_path = @datasource_path and pubid = @pubid
  21622.         END
  21623.     if @repid is NULL
  21624.         begin
  21625.             RAISERROR(20021, 16, -1)
  21626.             return (1)
  21627.         end
  21628.  
  21629.     update sysmergesubscriptions set status=1 where subid=@repid and (status=5 or status=0)
  21630.  
  21631.     if @schemaversion is not null
  21632.         begin
  21633.             update MSmerge_replinfo set schemaversion = @schemaversion where repid = @repid
  21634.             if @@error <> 0        
  21635.                 begin
  21636.                     RAISERROR(20054 , 16, -1)
  21637.                     return (1)
  21638.                 end
  21639.         end
  21640.         
  21641.     if @subid is not null and @subid <> @repid
  21642.         begin
  21643.         /* Fix the repid for pull subscribers before we copy around global replica rows */
  21644.         update MSmerge_replinfo set repid = @subid where repid = @repid
  21645.         if @@error <> 0        
  21646.             begin
  21647.                 RAISERROR(20054 , 16, -1)
  21648.                 return (1)
  21649.             end
  21650.         update sysmergesubscriptions set subid = @subid where subid = @repid
  21651.         if @@error <> 0        
  21652.             begin
  21653.                 RAISERROR(20054 , 16, -1)
  21654.                 return (1)
  21655.             end
  21656.         end
  21657.         
  21658.     if @nickname IS NOT NULL        
  21659.         begin
  21660.             /* If this nickname isn't already assigned, reset it */
  21661.             if exists (select * from MSmerge_replinfo, sysmergesubscriptions
  21662.                     where replnickname = @nickname and repid = subid and (srvid <> @srvid or
  21663.                                 db_name <> @db_name))
  21664.                 return (0)
  21665.             update MSmerge_replinfo set replnickname = @nickname where repid = @repid
  21666.             if @@error <> 0        
  21667.                 begin
  21668.                     RAISERROR(20054 , 16, -1)
  21669.                     return (1)
  21670.                 end
  21671.         end            
  21672.     
  21673.     return (0)
  21674. go
  21675.  
  21676. exec dbo.sp_MS_marksystemobject sp_MSsetreplicainfo
  21677. go
  21678. grant exec on dbo.sp_MSsetreplicainfo to public
  21679. go
  21680.  
  21681. raiserror('Creating procedure sp_MSsetreplicastatus', 0,1)
  21682. GO
  21683.  
  21684. CREATE PROCEDURE sp_MSsetreplicastatus
  21685.     (@subid uniqueidentifier,
  21686.      @status_value int
  21687.      ) AS
  21688.      
  21689.     /*
  21690.     ** Check to see if current publication has permission
  21691.     */
  21692.     declare @retcode int
  21693.  
  21694.     if sessionproperty('replication_agent') = 0
  21695.     begin
  21696.         exec @retcode=sp_MSreplcheck_connection
  21697.             @repid = @subid
  21698.         if @retcode<>0 or @@ERROR<>0 return (1)
  21699.     end
  21700.     
  21701.      IF EXISTS (select subid from sysmergesubscriptions where subid=@subid)
  21702.          begin
  21703.             update sysmergesubscriptions set status = @status_value, resync_gen=-1 WHERE subid=@subid                
  21704.              if @@ERROR<>0 return (1)
  21705.             -- Now that we have changed a replica's status we might be ready to
  21706.             -- cleanup metadata or something like that.
  21707.             exec @retcode = sp_MSquiescecheck                    
  21708.              if @@ERROR<>0 or @retcode <> 0 return (1)
  21709.          end
  21710.     return (0)
  21711. go
  21712. exec dbo.sp_MS_marksystemobject sp_MSsetreplicastatus
  21713. go
  21714. grant exec on dbo.sp_MSsetreplicastatus to public
  21715. go
  21716.  
  21717.  
  21718. raiserror('Creating procedure sp_MScreateglobalreplica', 0,1)
  21719. GO
  21720.  
  21721. CREATE PROCEDURE sp_MScreateglobalreplica(
  21722.     @pubid                     uniqueidentifier = NULL,            /* Publication ID */
  21723.     @subid                     uniqueidentifier,          /* Replica ID */
  21724.     @partnerid                 uniqueidentifier,          /* Partner's Replica ID */
  21725.     @replica_server            sysname,         /* Replica server */
  21726.     @replica_db                sysname,          /* Replica database */
  21727.     @replica_priority        real,                  /* Replica priority */
  21728.     @subscriber_type        tinyint = 0,        /* Replica's subscriber type - global, hub */
  21729.     @subscription_type         int = 0,            /* Replica's subscription type - push or pull */
  21730.     @datasource_type         int = 0,
  21731.     @datasource_path         nvarchar(255) = NULL,
  21732.     @nickname                int,                /* Replica nickname */
  21733.     @status                    int,                /* Replica status */
  21734.     @sync_type                 tinyint = 2,        /* Replica sync type 1 = no sync, 2 = automatic */
  21735.     @publication            sysname = NULL,        /* Replica publication */
  21736.     @distributor            sysname = NULL        /* Replica's distributor */
  21737.     ) AS
  21738.     
  21739.     SET NOCOUNT ON
  21740.  
  21741.     /*
  21742.     ** Declarations.
  21743.     */
  21744.     DECLARE @replica_srvid        int
  21745.     DECLARE @pubnickname        int
  21746.     declare @retcode            int
  21747.     /*
  21748.     ** Check to see if current publication has permission
  21749.     */
  21750.     if sessionproperty('replication_agent') = 0
  21751.     begin
  21752.         exec @retcode=sp_MSreplcheck_connection
  21753.             @pubid = @pubid
  21754.         if @retcode<>0 or @@ERROR<>0 return (1)
  21755.     end
  21756.     
  21757.     /*
  21758.     ** NOTE
  21759.     */
  21760.     select @replica_db = RTRIM(@replica_db)
  21761.     /* 
  21762.     ** Initializations
  21763.     */
  21764.     SELECT @replica_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@replica_server) collate database_default
  21765.     if @replica_srvid is NULL
  21766.         begin
  21767.         EXECUTE @retcode = dbo.sp_addserver @replica_server, @duplicate_ok='duplicate_ok'
  21768.  
  21769.         IF @@error <> 0 OR @retcode <> 0
  21770.             BEGIN
  21771.                 RAISERROR (14042, 16, -1)
  21772.                 RETURN (1)
  21773.             END
  21774.         end                
  21775.     SELECT @replica_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@replica_server) collate database_default
  21776.  
  21777.     BEGIN TRAN MScreateglobalreplica    
  21778.         /*
  21779.         ** Populate the local copy of sysmergesubscriptions
  21780.         */
  21781.         if exists (select * from sysmergesubscriptions where subid = @subid)
  21782.             begin
  21783.                 update sysmergesubscriptions 
  21784.                     SET    subid                 = @subid,
  21785.                         datasource_type     = @datasource_type,
  21786.                         datasource_path     = @datasource_path,
  21787.                         srvid                 = @replica_srvid,
  21788.                         db_name             = @replica_db,
  21789.                         pubid                 = @pubid,
  21790.                         status                 = @status,
  21791.                         subscriber_type     = @subscriber_type,
  21792.                         subscription_type     = @subscription_type,
  21793.                         priority             = @replica_priority,
  21794.                         sync_type            = @sync_type,
  21795.                         login_name            = suser_sname(suser_sid()),
  21796.                         subscriber_server    = @replica_server,
  21797.                         publication            = @publication,
  21798.                         distributor            = @distributor
  21799.                 where subid = @subid and pubid = @pubid                         
  21800.             IF @@ERROR <> 0
  21801.                 goto FAILURE
  21802.             end
  21803.         else
  21804.             begin
  21805.                 /* 
  21806.                 ** If attempting to tell the current replica about another replica whose pubid IS NULL
  21807.                 ** ignore the insert because current replica has more current info.
  21808.                 */
  21809.                 if exists (select * from sysmergesubscriptions where subid = @subid and @pubid IS NULL)
  21810.                     goto SUCCESS
  21811.                     
  21812.                 IF EXISTS (SELECT * FROM sysmergesubscriptions WHERE
  21813.                     srvid = @replica_srvid AND db_name = @replica_db and pubid = @pubid)
  21814.                     goto SUCCESS
  21815.                     
  21816.                 if not exists (select * from sysmergesubscriptions where subid=@subid)
  21817.                 begin
  21818.                     insert sysmergesubscriptions(subid, partnerid, datasource_type, datasource_path, 
  21819.                         srvid, db_name, pubid, status, subscriber_type, subscription_type, priority, 
  21820.                         sync_type, login_name, subscriber_server, publication, distributor)
  21821.                     values (@subid, @partnerid, @datasource_type, @datasource_path, 
  21822.                         @replica_srvid, @replica_db, @pubid, @status, @subscriber_type, @subscription_type, @replica_priority, 
  21823.                         @sync_type, suser_sname(suser_sid()), @replica_server, @publication, @distributor)
  21824.                     IF @@ERROR <> 0
  21825.                         goto FAILURE
  21826.                 end
  21827.             end
  21828.         if not exists (select * from MSmerge_replinfo where repid = @subid )
  21829.             begin
  21830.     
  21831.                 INSERT INTO  MSmerge_replinfo(repid, replnickname)    
  21832.                     values (@subid, @nickname) 
  21833.                 IF @@ERROR <> 0
  21834.                     goto FAILURE
  21835.             end
  21836. SUCCESS:            
  21837.     COMMIT TRAN            
  21838.     RETURN 0
  21839.  
  21840. FAILURE:
  21841.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  21842.     if @@TRANCOUNT = 1 
  21843.         ROLLBACK TRANSACTION MScreateglobalreplica
  21844.     else
  21845.         COMMIT TRANSACTION
  21846.     
  21847.     RAISERROR (14057, 16, -1)
  21848.     RETURN 1
  21849. go
  21850. exec dbo.sp_MS_marksystemobject sp_MScreateglobalreplica
  21851. go
  21852. grant exec on dbo.sp_MScreateglobalreplica to public
  21853. go
  21854.  
  21855. raiserror('Creating procedure sp_MSsetconflictscript', 0,1)
  21856. GO
  21857.  
  21858. /* Add the conflict script pointer to sysmergearticles - Used by snapshot */
  21859. CREATE PROCEDURE sp_MSsetconflictscript (
  21860.     @publication        sysname,
  21861.     @article            sysname,
  21862.     @conflict_script    nvarchar(255),
  21863.     @login                sysname =NULL,
  21864.     @password            nvarchar(524) =NULL
  21865.     ) AS
  21866.  
  21867.     declare @artid uniqueidentifier
  21868.     declare @pubid uniqueidentifier
  21869.     
  21870.     /*
  21871.     ** Check for publish permission.
  21872.     */
  21873.     declare @retcode int
  21874.     exec @retcode=sp_MSreplcheck_publish
  21875.     if @retcode<>0 or @@ERROR<>0 return (1)
  21876.     
  21877.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  21878.     if @pubid IS NULL
  21879.         BEGIN
  21880.             RAISERROR (20026, 16, -1, @publication)
  21881.             RETURN (1)
  21882.         END
  21883.     
  21884.     select @artid = artid FROM sysmergearticles WHERE name = @article    AND pubid = @pubid
  21885.     if @artid IS NULL
  21886.         BEGIN
  21887.             RAISERROR (20027, 16, -1, @article)
  21888.             RETURN (1)
  21889.         END
  21890.  
  21891.     update sysmergearticles set conflict_script = @conflict_script where artid = @artid and pubid=@pubid
  21892.     if @@ERROR <> 0
  21893.         return (1)
  21894.     return (0)
  21895. go
  21896. exec dbo.sp_MS_marksystemobject sp_MSsetconflictscript 
  21897. go
  21898. grant exec on dbo.sp_MSsetconflictscript to public
  21899. go
  21900.  
  21901. raiserror('Creating procedure sp_MSsetconflicttable', 0,1)
  21902. GO
  21903.  
  21904. /* Add the conflict table pointer to sysmergearticles - Used by reconciler */
  21905. CREATE PROCEDURE sp_MSsetconflicttable (
  21906.     @article            sysname,
  21907.     @conflict_table        nvarchar(255),
  21908.     @publisher            sysname = NULL,
  21909.     @publisher_db        sysname = NULL, 
  21910.     @publication        sysname = NULL
  21911.     ) AS
  21912.  
  21913.     declare @artid uniqueidentifier
  21914.     declare @pubid uniqueidentifier
  21915.     declare @quoted_conflict_table nvarchar(270)
  21916.     declare @basetableid    int
  21917.     
  21918.     --special case'd this out for backward compatibility with 7.0 subscribers.
  21919.     if @publisher is NULL and @publisher_db is NULL and @publication is NULL
  21920.         return (0)
  21921.  
  21922.     select @pubid=pubid    from sysmergepublications 
  21923.         where name=@publication and LOWER(publisher)=LOWER(@publisher) and publisher_db=@publisher_db
  21924.         
  21925.     select @artid = artid, @basetableid=objid FROM sysmergearticles WHERE name = @article and pubid=@pubid    
  21926.     if @artid IS NULL
  21927.         BEGIN
  21928.             RAISERROR (20027, 16, -1, @article)
  21929.             RETURN (1)
  21930.         END
  21931.  
  21932.     /*
  21933.     ** Check to see if current publication has permission
  21934.     */
  21935.     declare @retcode int
  21936.  
  21937.     if sessionproperty('replication_agent') = 0
  21938.     begin
  21939.         exec @retcode=sp_MSreplcheck_connection
  21940.             @artid = @artid
  21941.         if @retcode<>0 or @@ERROR<>0 return (1)
  21942.     end
  21943.  
  21944.     select @quoted_conflict_table = quotename(@conflict_table)
  21945.     exec @retcode = dbo.sp_MS_marksystemobject @quoted_conflict_table
  21946.     
  21947.     update sysmergearticles set conflict_table = @conflict_table where artid = @artid and pubid=@pubid
  21948.     if @@ERROR <> 0
  21949.         return (1)
  21950.  
  21951.     declare @rgcol nvarchar(135)
  21952.     declare @indname nvarchar(131)
  21953.     declare @owner sysname
  21954.     declare @quotedname nvarchar(270)
  21955.         
  21956.     select @rgcol = QUOTENAME(name) from syscolumns where id = @basetableid and
  21957.                 ColumnProperty(id, name, 'isrowguidcol') = 1
  21958.     select @owner=user_name(uid) from sysobjects where name=@conflict_table
  21959.     select @indname = 'uc_' + @conflict_table
  21960.     if len(@indname) > 128
  21961.         begin
  21962.             select @indname = substring(@indname,1,92) + convert(nvarchar(36), newid())
  21963.         end
  21964.     set @indname = QUOTENAME(@indname)
  21965.     set @quotedname = QUOTENAME(@owner) + '.' + QUOTENAME(@conflict_table)
  21966.  
  21967.     --only create the conflict table index when needed.
  21968.     if not exists (select * from sysindexes where id = object_id(@quotedname) and keys is not null)
  21969.         begin
  21970.             exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname +
  21971.                     ' (' + @rgcol + ', origin_datasource)' )
  21972.             if @@error <> 0
  21973.                 return (1)
  21974.         end
  21975.  
  21976.     /* Create the conflict insert proc only when necessary for performance reason */
  21977.     if exists (select * from sysmergearticles where artid = @artid and pubid=@pubid and OBJECT_ID(ins_conflict_proc) is null)
  21978.         BEGIN
  21979.         exec dbo.sp_MSgetconflictinsertproc @pubid=@pubid, @artid = @artid, @output = 0
  21980.         IF @@ERROR<> 0 OR @retcode <> 0
  21981.             return (1)
  21982.         END
  21983.  
  21984.     return (0)
  21985. go
  21986. exec dbo.sp_MS_marksystemobject sp_MSsetconflicttable 
  21987. go
  21988. grant exec on dbo.sp_MSsetconflicttable to public
  21989. go
  21990.  
  21991. raiserror('Creating procedure sp_MSmakeconflictinsertproc', 0,1)
  21992. GO
  21993.  
  21994. create procedure sp_MSmakeconflictinsertproc 
  21995.     (@tablename sysname, @ownername sysname, @procname sysname, @basetableid int, @pubid uniqueidentifier=NULL)
  21996. as
  21997. declare @arglist    nvarchar(4000)
  21998. declare @header        nvarchar(4000)
  21999. declare @qualname   nvarchar(270)
  22000. declare @argname    nvarchar(270)
  22001. declare @noset        bit
  22002. declare @wherepc    nvarchar(255)
  22003. declare @id         int
  22004. declare @sync_objid    int
  22005. declare @colname nvarchar(140)
  22006. declare @typename sysname
  22007. declare @colid smallint
  22008. declare @status tinyint
  22009. declare @len smallint
  22010. declare @prec smallint
  22011. declare @scale int
  22012. declare @retcode smallint
  22013. declare @sys_loop bit
  22014. declare @old_colname nvarchar(140)
  22015. declare @create_time_col nvarchar(8)
  22016. declare @p_number_for_conflict_type nvarchar(270)
  22017.  
  22018. set nocount on
  22019.  
  22020. select @sys_loop = 0
  22021. set @create_time_col = NULL
  22022. set @id = NULL
  22023.  
  22024. /*
  22025. ** To check if specified object exists in current database
  22026. */
  22027. select @id = id, @ownername=user_name(uid) from sysobjects where name = @tablename
  22028.     if @id is NULL return (1)
  22029.  
  22030. set @qualname = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
  22031.  
  22032. -- create temp table to select the command text out of
  22033. create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, 
  22034. cmdtext nvarchar(4000) collate database_default null)
  22035.  
  22036. select @header = 'Create procedure dbo.' + @procname + ' ( ' 
  22037. insert into #tempcmd (phase, cmdtext) values (0,  @header)
  22038.  
  22039. select @sync_objid = sync_objid from sysmergearticles where objid = @basetableid and (pubid = @pubid or @pubid is NULL)
  22040.  
  22041. select @colid = min(colid) from syscolumns where id = @id and iscomputed <>1 and 
  22042.     type_name(xtype) <> 'timestamp' and ((name not in (select name from syscolumns where id=@basetableid) 
  22043.         and @sys_loop =1) OR
  22044.      (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0))
  22045. select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
  22046.     @prec = c.prec, @scale = c.scale
  22047.     from syscolumns c, systypes t
  22048.     where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype 
  22049.  
  22050. /*
  22051. ** Get the column list from the conflict_table schema and filter it with 
  22052. table view for vertical partitioning
  22053. */
  22054. Reverse_Order:
  22055. while (@colname is not null) 
  22056. begin
  22057.     set @noset = 0
  22058.     if exists (select * from syscolumns where name=@colname and id=@basetableid)
  22059.         and not exists (select * from syscolumns where name=@colname and id=@sync_objid)
  22060.         goto NEXT_COL         
  22061.     if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  22062.         select @len = @len/2
  22063.     exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  22064.     if @@ERROR<>0 or @retcode<>0 return (1)
  22065.     select @argname = '@p' + rtrim(convert(nchar, @colid))
  22066.     
  22067.     if LOWER(@colname collate SQL_Latin1_General_CP1_CS_AS)='conflict_type'
  22068.         select @p_number_for_conflict_type=@argname
  22069.         
  22070.     -- based on colid, add text to appropriate pieces
  22071.     if (COLUMNPROPERTY( @basetableid, @colname, 'IsRowGuidCol') = 1)  
  22072.         begin
  22073.             select @noset =1
  22074.             set @wherepc = ' where rowguidcol = ' + @argname
  22075.         end
  22076.     else if (@colname = 'origin_datasource')
  22077.         begin
  22078.             select @wherepc =@wherepc +  ' and origin_datasource = ' + @argname
  22079.             set @noset =1
  22080.         end
  22081.     set @old_colname = @colname
  22082.     set @colname = QUOTENAME(@colname)
  22083.     if @arglist is null
  22084.         begin
  22085.         set @arglist = @argname + ' ' + @typename
  22086.         --give default value of NULL to new merge columns for backward compatibility concern
  22087.         insert into #tempcmd (phase, cmdtext) values (3, @colname)
  22088.         select @header = ') values ('
  22089.         insert into #tempcmd (phase, cmdtext) values (4, @header)
  22090.  
  22091.         insert into #tempcmd (phase, cmdtext) values (4, @argname)
  22092.         if @noset=0
  22093.             insert into #tempcmd (phase, cmdtext) values (1, @colname + ' = ' + @argname)
  22094.         end
  22095.     else 
  22096.         begin
  22097.         if len(@arglist)>3700
  22098.             begin
  22099.                 insert into #tempcmd (phase, cmdtext) values (0,  @arglist)            
  22100.                 select @arglist = ' '
  22101.             end
  22102.         set @arglist = @arglist + ', ' + @argname + ' ' + @typename
  22103.         if @sys_loop = 1 and @old_colname not in ('origin_datasource','conflict_type','reason_code','reason_text', 'pubid') 
  22104.             begin
  22105.                 select @arglist=@arglist + ' = NULL'        
  22106.                 if @old_colname='MSrepl_create_time'
  22107.                     select @create_time_col=@argname
  22108.             end
  22109.  
  22110.         insert into #tempcmd (phase, cmdtext) values (3, ',' + @colname)
  22111.  
  22112.         insert into #tempcmd (phase, cmdtext) values (4, ',' + @argname)
  22113.  
  22114.         if @noset =0
  22115.             begin
  22116.                 if exists (select * from #tempcmd where phase=1)
  22117.                     insert into #tempcmd (phase, cmdtext) values (1, ',' + @colname + ' = ' + @argname)
  22118.                 else
  22119.                     insert into #tempcmd (phase, cmdtext) values (1, @colname + ' = ' + @argname)
  22120.             end
  22121.         end
  22122. NEXT_COL:
  22123.     select @colid = min(colid) from syscolumns where id = @id and colid>@colid and iscomputed <>1 and 
  22124.         type_name(xtype) <> 'timestamp' and 
  22125.         ((name not in (select name from syscolumns where id=@basetableid) and @sys_loop =1) OR
  22126.              (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0))
  22127.     set @colname = NULL
  22128.     select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
  22129.         @prec = c.prec, @scale = c.scale
  22130.         from syscolumns c, systypes t
  22131.         where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype
  22132. end
  22133.  
  22134. if @sys_loop = 0
  22135. begin
  22136.     select @sys_loop = 1
  22137.     select @colid = min(colid) from syscolumns where id = @id  and iscomputed <>1 
  22138.         and type_name(xtype) <> 'timestamp' and 
  22139.         ((name not in (select name from syscolumns where id=@basetableid) and @sys_loop =1) OR
  22140.          (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0))
  22141.     select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
  22142.         @prec = c.prec, @scale = c.scale
  22143.         from syscolumns c, systypes t
  22144.             where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype 
  22145.     goto Reverse_Order
  22146. end
  22147.  
  22148. -- now create the procedure
  22149. select @procname = QUOTENAME(@procname)
  22150.  
  22151. insert into #tempcmd (phase, cmdtext) values (0,  @arglist)            
  22152.  
  22153. select @header =  ') as'
  22154. insert into #tempcmd (phase, cmdtext) values (0,  @header)
  22155.  
  22156. select @header = ' '
  22157. -- for ease of expansion here in case we add new merge columns in conflict tables.
  22158. if @create_time_col is not NULL
  22159.     select @header = @header + ' 
  22160.         select ' + @create_time_col + ' = getdate() '
  22161.  
  22162. select @header = @header + ' if exists (select * from ' + @qualname + ' ' + @wherepc + ')
  22163.     begin
  22164.     update ' + @qualname + ' set ' 
  22165. insert into #tempcmd (phase, cmdtext) values (0,  @header)
  22166.  
  22167. --see comment in sp_MSinsertdeleteconflict for this <5 or >4 checking.
  22168.  
  22169. select @header = @wherepc + ' and (conflict_type<5 or ' + @p_number_for_conflict_type + ' >4) 
  22170.     end
  22171.     else
  22172.     insert into ' + @qualname + ' ('
  22173. insert into #tempcmd (phase, cmdtext) values (2,  @header)
  22174.  
  22175. insert into #tempcmd (phase, cmdtext) values (4, ')')
  22176.  
  22177. -- Now we select out the command text pieces in proper order so that our caller,
  22178. -- xp_execresultset will execute the command that creates the stored procedure.
  22179.  
  22180. select cmdtext from #tempcmd order by phase, step
  22181. drop table #tempcmd
  22182. go
  22183. exec dbo.sp_MS_marksystemobject sp_MSmakeconflictinsertproc 
  22184. go
  22185. grant exec on dbo.sp_MSmakeconflictinsertproc to public
  22186. go
  22187.  
  22188. dump tran master with no_log
  22189. go
  22190.  
  22191.  
  22192. raiserror('Creating procedure sp_MSmaketempinsertproc', 0,1)
  22193. GO
  22194.  
  22195. -- Create temp sp, no security check needed
  22196. create procedure sp_MSmaketempinsertproc 
  22197.     (@tablename sysname, @procname sysname)
  22198. as
  22199. declare @arglist    nvarchar(4000)
  22200. declare @collist    nvarchar(4000)
  22201. declare @vallist     nvarchar(4000)
  22202. declare @argname    sysname
  22203. declare @setpc        nvarchar(4000)
  22204. declare @wherepc    nvarchar(255)
  22205.  
  22206. declare @qualname nvarchar(270)
  22207. declare @id int
  22208.  
  22209. set @qualname = 'tempdb..' + @tablename
  22210. select @id = id from tempdb..sysobjects where name = @tablename
  22211.  
  22212. declare @colname sysname
  22213. declare @typename sysname
  22214. declare @colid smallint
  22215. declare @status tinyint
  22216. declare @len smallint
  22217. declare @prec int
  22218. declare @scale int
  22219. declare @retcode smallint
  22220.  
  22221.     
  22222. set @wherepc = ' where rowguid = @p2 '
  22223. select @colid = 1
  22224. select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
  22225.     @prec = COLUMNPROPERTY(c.id, c.name, 'precision'), @scale = c.scale
  22226.     from tempdb..syscolumns c, systypes t
  22227.     where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype and c.iscomputed<>1 and type_name(c.xtype) <> 'timestamp' 
  22228. while (@colname is not null)
  22229.     begin
  22230.     if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  22231.         select @len = @len/2
  22232.     exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  22233.     if @@error<>0 or @retcode<>0 return (1)
  22234.  
  22235.     set @argname = '@p' + rtrim(convert(nchar, @colid))
  22236.             
  22237.     if (@colid = 1)
  22238.         begin
  22239.         set @arglist = @argname + ' ' + @typename
  22240.         set @collist = @colname
  22241.         set @vallist = @argname
  22242.         set @setpc = @colname + ' = ' + @argname
  22243.         end
  22244.     else
  22245.         begin
  22246.         set @arglist = @arglist + ', ' + @argname + ' ' + @typename
  22247.         set @collist = @collist + ', ' + @colname
  22248.         set @vallist = @vallist + ', ' + @argname
  22249.         set @setpc = @setpc + ', ' + @colname + ' = ' + @argname
  22250.         end
  22251.     set @colid = @colid + 1
  22252.     set @colname = NULL
  22253.     select @colname = c.name, @status = c.status, @typename = t.name, @len = c.length,
  22254.         @prec = COLUMNPROPERTY(c.id, c.name, 'precision'), @scale = c.scale
  22255.         from tempdb..syscolumns c, systypes t
  22256.         where c.id = @id and c.colid = @colid and c.xusertype = t.xusertype 
  22257.             and c.iscomputed<>1 and type_name(c.xtype)<>'timestamp' 
  22258.     end
  22259. declare @qual_tablename nvarchar(140)
  22260. declare @qual_procname nvarchar(140)
  22261. select @qual_procname = QUOTENAME(@procname)
  22262. select @qual_tablename = QUOTENAME(@tablename)
  22263. -- now create the procedure
  22264. execute ('Create procedure dbo.' + @qual_procname + ' ( ' + @arglist + ') as
  22265.     update ' + @qual_tablename + ' set ' + @setpc + @wherepc + '
  22266.     if (@@rowcount = 0)
  22267.     insert into ' + @qual_tablename + ' (' + @collist + ') values (' + @vallist + ')')
  22268. if @@ERROR<>0
  22269.     begin
  22270.         return(1)
  22271.     end
  22272. go
  22273. exec dbo.sp_MS_marksystemobject sp_MSmaketempinsertproc 
  22274. go
  22275. grant exec on dbo.sp_MSmaketempinsertproc to public
  22276. go
  22277.  
  22278. raiserror('Creating procedure sp_MSgetconflictinsertproc', 0,1)
  22279. GO
  22280.  
  22281. /* Add the conflict table pointer to sysmergearticles - Used by reconciler */
  22282. CREATE PROCEDURE sp_MSgetconflictinsertproc (
  22283.     @artid                 uniqueidentifier,
  22284.     @pubid                uniqueidentifier = NULl,
  22285.     @output    int = 1
  22286.     ) AS
  22287.     declare @conflict_table sysname
  22288.     declare @conflict_proc    sysname
  22289.     declare @owner             sysname
  22290.     declare @object            sysname
  22291.     declare @retcode         int
  22292.     declare @quoted_conflict_table    nvarchar(270)
  22293.     declare    @basetableid    int
  22294.     declare @sync_objid            int
  22295.     declare @command              nvarchar(1000)
  22296.     declare @pubidstr             nvarchar(40)
  22297.     declare @dbname                sysname
  22298.     declare @conflict_table_id     int
  22299.     -- PARSENAME VARS
  22300.     declare @UnqualName     nvarchar(270)  --rightmost name node
  22301.     declare @QualName1      nvarchar(270)  
  22302.     declare @QualName2      nvarchar(270)  
  22303.     -- END PARSENAME VARS
  22304.  
  22305.     declare @guidstr varchar(40)
  22306.     exec @retcode=sp_MSguidtostr @artid, @guidstr out
  22307.     if @retcode<>0 or @@ERROR<>0 return (1)
  22308.     
  22309.     /*
  22310.     ** Check to see if current publication has permission
  22311.     */
  22312.     if sessionproperty('replication_agent') = 0
  22313.     begin
  22314.         exec @retcode=sp_MSreplcheck_connection
  22315.             @artid = @artid
  22316.         if @retcode<>0 or @@ERROR<>0 return (1)
  22317.     end
  22318.  
  22319.     /*
  22320.     ** @pubid is NULL - means that subscriber is 7.0, in which case there is no
  22321.     ** vertical partitioning allowed. getting the proc from any publication is fine.
  22322.     */
  22323.     select @conflict_table = conflict_table, @conflict_proc = ins_conflict_proc, 
  22324.             @basetableid = objid, @sync_objid = sync_objid 
  22325.     from sysmergearticles where artid = @artid and (pubid=@pubid OR @pubid is NULL)
  22326.  
  22327.     if @@ERROR <> 0
  22328.         return (1)
  22329.  
  22330.     select @conflict_table_id = object_id(@conflict_table)
  22331.     if @conflict_table_id is NULL  --check if it is caused by different owner name
  22332.         select @conflict_table_id=id from sysobjects where name=@conflict_table
  22333.  
  22334.     select @quoted_conflict_table = QUOTENAME(@conflict_table)
  22335.     if ( @conflict_table_id is not null)
  22336.     begin            
  22337.         select @UnqualName = PARSENAME(@conflict_table, 1)
  22338.         select @QualName1 = PARSENAME(@conflict_table, 2)
  22339.         if @UnqualName IS NULL
  22340.              return 1
  22341.         
  22342.         -- fixup for variable length differences.  remove when vars expanded
  22343.         -- to new SQL SERVER 7.0 lengths
  22344.  
  22345.         select @owner=user_name(uid) from sysobjects where id= @conflict_table_id
  22346.         if @owner is NULL
  22347.         begin
  22348.             select @owner =  @QualName1
  22349.         end
  22350.         select @object = @UnqualName
  22351.     end
  22352.     
  22353.     -- Create an index on the conflict table if it doesn't have one
  22354.     if ( @conflict_table_id is not null) and
  22355.         not exists (select * from sysindexes where id = @conflict_table_id and keys is not null)
  22356.         begin
  22357.         declare @rgcol nvarchar(135)
  22358.         declare @indname nvarchar(270)
  22359.         declare @quotedname nvarchar(270)
  22360.         
  22361.         select @rgcol = QUOTENAME(name) from syscolumns where id = @basetableid and
  22362.                 ColumnProperty(id, name, 'isrowguidcol') = 1
  22363.         select @indname = 'uc_' + @conflict_table
  22364.         if len(@indname) > 128
  22365.         begin
  22366.             select @indname = substring(@indname,1,92) + convert(nvarchar(36), newid())
  22367.         end
  22368.         set @indname = QUOTENAME(@indname)
  22369.         set @quotedname = QUOTENAME(@owner) + '.' + QUOTENAME(@conflict_table)
  22370.         exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname +
  22371.                 ' (' + @rgcol + ', origin_datasource)' )
  22372.         if @@error <> 0
  22373.             return (1)
  22374.         end
  22375.     if ((OBJECT_ID(@conflict_proc) is null) and (@conflict_table_id is not null))
  22376.         begin
  22377.         -- first set up the procedure name variable
  22378.  
  22379.         exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
  22380.         if @@ERROR <>0 OR @retcode <>0 return (1)
  22381.  
  22382.         exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  22383.         if @@ERROR <>0 OR @retcode <>0 return (1)
  22384.  
  22385.         if @pubid is not NULL
  22386.             select @conflict_proc = 'sp_cft_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22387.         else
  22388.             select @conflict_proc = 'sp_cft_' + substring(@guidstr, 1, 32) 
  22389.  
  22390.         exec @retcode=sp_MSuniqueobjectname @conflict_proc , @conflict_proc output
  22391.         if @@ERROR <> 0 OR @retcode <> 0 
  22392.             return(1)
  22393.         set @dbname = db_name()
  22394.         if @owner is NULL
  22395.             set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , NULL , ' + @conflict_proc  + ' , ' + convert(nvarchar,@basetableid)
  22396.         else
  22397.             set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , ' + QUOTENAME(@owner) + ' , ' + @conflict_proc  + ' , ' + convert(nvarchar,@basetableid) 
  22398.  
  22399.         if @pubid is not NULL
  22400.             set @command = @command    + ', [' + convert(nchar(36), @pubid) + ']'
  22401.         exec @retcode = master..xp_execresultset @command, @dbname
  22402.         if @@ERROR<>0 OR @retcode<>0 
  22403.         begin
  22404.             return (1)
  22405.         end
  22406.         exec @retcode = dbo.sp_MS_marksystemobject  @conflict_proc 
  22407.         if @@ERROR<>0 or @retcode<>0  return (1)
  22408.         exec ('grant exec on ' + @conflict_proc + ' to public')
  22409.         if @@ERROR<>0 return (1)
  22410.         update sysmergearticles set ins_conflict_proc = @conflict_proc where artid = @artid and pubid=@pubid
  22411.     end
  22412.  
  22413.     if @output = 1
  22414.         select @conflict_table, @conflict_proc
  22415.     if @@ERROR <> 0
  22416.         return (1)
  22417.     return (0)
  22418.     
  22419. go
  22420. exec dbo.sp_MS_marksystemobject sp_MSgetconflictinsertproc 
  22421. go
  22422. grant exec on dbo.sp_MSgetconflictinsertproc to public
  22423. go
  22424.  
  22425. raiserror('Creating procedure sp_MSinsertdeleteconflict', 0,1)
  22426. GO
  22427.  
  22428. create PROCEDURE sp_MSinsertdeleteconflict(     
  22429.     @tablenick             int,
  22430.     @rowguid             uniqueidentifier,
  22431.     @conflict_type        int,
  22432.     @reason_code        int,
  22433.     @reason_text        nvarchar(720),
  22434.     @origin_datasource    nvarchar(255),
  22435.     @pubid                uniqueidentifier,
  22436.     @lineage             varbinary(255) = NULL,
  22437.     @conflicts_logged    INT = NULL OUTPUT)
  22438. as
  22439.     
  22440.     declare @retcode int
  22441.     /*
  22442.     ** Check to see if current publication has permission
  22443.     */
  22444.     if sessionproperty('replication_agent') = 0
  22445.     begin
  22446.         exec @retcode=sp_MSreplcheck_connection
  22447.             @tablenick = @tablenick
  22448.         if @retcode<>0 or @@ERROR<>0 return (1)
  22449.     end
  22450.  
  22451.     /* Parameter validation */
  22452.     if (@tablenick is null)
  22453.         begin
  22454.         RAISERROR(14043, 16, -1, '@tablenick')
  22455.         return (1)
  22456.         end
  22457.     if (@rowguid is null)
  22458.         begin
  22459.         RAISERROR(14043, 16, -1, '@rowguid')
  22460.         return (1)
  22461.         end
  22462.  
  22463.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  22464.         begin
  22465.         RAISERROR(20054 , 16, -1)
  22466.         return (1)
  22467.         end
  22468.     /* Don't insert a duplicate row */
  22469.     if (not exists (select * from MSmerge_delete_conflicts where tablenick = @tablenick and
  22470.         rowguid = @rowguid and origin_datasource = @origin_datasource))
  22471.         begin
  22472.             insert into MSmerge_delete_conflicts
  22473.                 (tablenick, rowguid, conflict_type, reason_code, reason_text, origin_datasource, pubid) values
  22474.                 (@tablenick, @rowguid, @conflict_type, @reason_code, @reason_text, @origin_datasource, @pubid)
  22475.             select @conflicts_logged = @@ROWCOUNT
  22476.             if @@ERROR <> 0 return (1)
  22477.         end
  22478.         /* Update the existing row - but do not use a generic message to update an error */
  22479.     else if (exists (select * from MSmerge_delete_conflicts where tablenick = @tablenick and
  22480.                 rowguid = @rowguid and origin_datasource = @origin_datasource and 
  22481.                 (conflict_type<5 or @conflict_type>4)))
  22482.         begin                
  22483.             update MSmerge_delete_conflicts set conflict_type = @conflict_type, reason_code = @reason_code,
  22484.                 reason_text = @reason_text where tablenick = @tablenick and
  22485.                 rowguid = @rowguid and origin_datasource = @origin_datasource
  22486.             select @conflicts_logged = @@ROWCOUNT
  22487.             if @@ERROR <> 0 return (1)
  22488.         end            
  22489.     
  22490.     /* If this is an error, add to MSmerge_errorlineage table */
  22491.     if @conflict_type in (7, 8) and @lineage is not null
  22492.         exec @retcode = sp_MSinserterrorlineage @tablenick, @rowguid, @lineage
  22493.     if @retcode<>0 or @@ERROR<>0 return (1)
  22494.     
  22495.     return (0)
  22496. go
  22497. exec dbo.sp_MS_marksystemobject sp_MSinsertdeleteconflict
  22498. go
  22499. grant exec on dbo.sp_MSinsertdeleteconflict to public
  22500. go
  22501.  
  22502. raiserror('Creating procedure sp_MScheckmetadatamatch', 0,1)
  22503. GO
  22504.  
  22505. create procedure sp_MScheckmetadatamatch
  22506.     (@metatype tinyint, 
  22507.      @rowguid uniqueidentifier,
  22508.      @tablenick int,
  22509.      @lineage varbinary(255),
  22510.      @match int output)
  22511. as
  22512.     if (@metatype = 3)
  22513.     begin
  22514.         if not exists (select * from dbo.MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid)
  22515.             select @match = 1
  22516.         else
  22517.             select @match = count(*) from dbo.MSmerge_contents (updlock) where
  22518.                 tablenick = @tablenick and rowguid = @rowguid and lineage = @lineage
  22519.     end
  22520.     else
  22521.         select @match = count(*) from dbo.MSmerge_contents (updlock) where
  22522.                 tablenick = @tablenick and rowguid = @rowguid and lineage = @lineage
  22523.     return (0)
  22524. go
  22525. exec dbo.sp_MS_marksystemobject sp_MScheckmetadatamatch
  22526. go
  22527. grant exec on dbo.sp_MScheckmetadatamatch to public
  22528.  
  22529. raiserror('Creating procedure sp_MSdelrow', 0,1)
  22530. GO
  22531.  
  22532. create PROCEDURE sp_MSdelrow 
  22533.     (@rowguid         uniqueidentifier,
  22534.     @tablenick     int,
  22535.     @metadata_type tinyint, /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred, 6 - system delete */
  22536.     @lineage_old varbinary(255),
  22537.     @generation int,
  22538.     @lineage_new varbinary(255),
  22539.     @pubid uniqueidentifier = NULL,
  22540.     @check_permission int = 0)
  22541.  
  22542. as
  22543.     set nocount on
  22544.     declare @match             int
  22545.     declare @new_metatype    tinyint
  22546.     declare @retcode         smallint
  22547.     declare @errcode        int
  22548.     declare @reason         nvarchar(255)
  22549.     declare @procname         sysname
  22550.     declare @objid            int
  22551.     declare @permissions    int
  22552.     
  22553.     /*
  22554.     ** Check to see if current publication has permission
  22555.     */
  22556.     if sessionproperty('replication_agent') = 0
  22557.     begin
  22558.         exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  22559.         if @retcode<>0 or @@ERROR<>0 return (0)
  22560.     end
  22561.             
  22562.     /* Parameter validation */
  22563.     if (@rowguid is null)
  22564.     begin
  22565.         RAISERROR(14043, 16, -1, '@rowguid')
  22566.         return (0)
  22567.     end
  22568.     if (@tablenick is null)
  22569.     begin
  22570.         RAISERROR(14043, 16, -1, '@tablenick')
  22571.         return (0)
  22572.     end
  22573.     if (@lineage_new is null)
  22574.     begin
  22575.         RAISERROR(14043, 16, -1, '@lineage_new')
  22576.         return (0)
  22577.     end
  22578.  
  22579.     if @check_permission =1
  22580.     begin
  22581.         select @objid=objid, @permissions= check_permissions from sysmergearticles 
  22582.             where nickname=@tablenick and (pubid is NULL or pubid=@pubid)
  22583.         if @objid is NULL
  22584.             return (0)
  22585.  
  22586.         exec @retcode = dbo.sp_MSreplcheck_permission @objid = @objid, @type = 3, @permissions = @permissions
  22587.         if @retcode<>0 or @@ERROR<>0 return (4)
  22588.     end
  22589.  
  22590.     -- Are we just changing the type of a tombstone?
  22591.     -- This routine is only called for Upload; won't be type 5 (remove from partial) unless
  22592.     -- subscriber has a user delete and found an existing metadata type of 5 here.
  22593.     -- In that case, set delete type to 1 and update generation, reason text too.
  22594.     if (@metadata_type = 5)
  22595.     begin
  22596.         if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  22597.         begin
  22598.             set @reason = formatmessage (20562) -- User delete
  22599.             update dbo.MSmerge_tombstone set type = 1, reason = @reason, generation = @generation, lineage = @lineage_new where
  22600.                 rowguid = @rowguid and tablenick = @tablenick
  22601.             return 1
  22602.         end
  22603.     end
  22604.     -- Are we just changing the type of a tombstone?
  22605.     else if (@metadata_type = 6)
  22606.     begin
  22607.         if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  22608.         begin
  22609.             set @reason = formatmessage (20564) -- System deleted
  22610.             update dbo.MSmerge_tombstone set type = @metadata_type, reason = @reason,
  22611.                 generation = @generation, lineage = @lineage_new where
  22612.                 rowguid = @rowguid and tablenick = @tablenick
  22613.             return 1
  22614.         end
  22615.     end
  22616.  
  22617.     -- begin transaction and lock row that we plan to delete
  22618.     begin transaction
  22619.     save tran sp_MSdelrow
  22620.  
  22621.     select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid = @pubid
  22622.     exec @retcode = @procname @type =8, @rowguid=@rowguid
  22623.     IF @@ERROR<>0 or @retcode<>0
  22624.     begin
  22625.         set @errcode= 0
  22626.         goto Failure
  22627.     end
  22628.  
  22629.     if @metadata_type = 5
  22630.     begin
  22631.         set @match = 1
  22632.         set @new_metatype = 5
  22633.     end
  22634.     else if @metadata_type = 6
  22635.     begin
  22636.         set @match = 1
  22637.         set @new_metatype = 6
  22638.     end
  22639.     else
  22640.     begin
  22641.         exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
  22642.         IF @@ERROR<>0 or @retcode<>0
  22643.         begin
  22644.             set @errcode= 0
  22645.             goto Failure
  22646.         end
  22647.         
  22648.         set @new_metatype = 1
  22649.     end
  22650.     
  22651.     if (@match = 1)
  22652.     begin
  22653.         -- select_proc makes a delete with @type = 5, despite its name. 
  22654.         declare @rowcount int, @error int
  22655.         exec @retcode = @procname @type =5, @rowguid=@rowguid
  22656.         select @error=@@error, @rowcount=@@rowcount
  22657.         if @error<>0 or @retcode<>0
  22658.         begin
  22659.             set @errcode= 0
  22660.             goto Failure
  22661.         end
  22662.         
  22663.         if (@rowcount = 1)
  22664.         begin
  22665.             exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  22666.             IF @@ERROR<>0 or @retcode<>0
  22667.             begin
  22668.                 set @errcode= 0
  22669.                 goto Failure
  22670.             end
  22671.         end
  22672.         else
  22673.         begin
  22674.             set @errcode= 3
  22675.             goto Failure
  22676.         end
  22677.     end
  22678.     else
  22679.     begin
  22680.         set @errcode= 2
  22681.         goto Failure
  22682.     end
  22683.  
  22684.     commit tran
  22685.     return(1)-- in sp_MSdelrow, 1=okay
  22686.  
  22687. Failure:
  22688.     rollback tran sp_MSdelrow
  22689.     commit tran
  22690.     return(@errcode)
  22691. go
  22692. exec dbo.sp_MS_marksystemobject sp_MSdelrow 
  22693. go
  22694. grant exec on dbo.sp_MSdelrow to public
  22695. go
  22696.  
  22697. raiserror('Creating procedure sp_MSsetartprocs', 0,1)
  22698. GO
  22699.  
  22700. SET ANSI_NULLS ON 
  22701. SET QUOTED_IDENTIFIER ON
  22702. GO
  22703. -- Call by snapshot
  22704. create procedure sp_MSsetartprocs
  22705.     (@publication        sysname,
  22706.     @article            sysname,
  22707.     @force_flag         int = 0)
  22708. as
  22709.     declare @ownername sysname
  22710.     declare @objectname sysname
  22711.     declare @guidstr nvarchar(40)
  22712.     declare @pubidstr nvarchar(40)
  22713.     declare @conflict_proc sysname
  22714.     declare @conflict_table sysname
  22715.     declare @snapshot_ready int
  22716.     declare @ins_procname sysname
  22717.     declare @sel_procname sysname
  22718.     declare @upd_procname sysname
  22719.     declare @view_selprocname nvarchar(290)
  22720.     declare @viewname sysname
  22721.     declare @artid uniqueidentifier
  22722.     declare @pubid uniqueidentifier
  22723.     declare @objid int
  22724.     declare @rgcol nvarchar(140)
  22725.     declare @sync_objid int
  22726.     declare @retcode smallint
  22727.     declare @dbname sysname
  22728.     declare @command  nvarchar(1000)
  22729.     
  22730.     set nocount on
  22731.     /*
  22732.     ** Check to see if current publication has permission
  22733.     */
  22734.     exec @retcode=sp_MSreplcheck_publish
  22735.     if @retcode<>0 or @@ERROR<>0 return (1)
  22736.     
  22737.     -- figure out pubid and artid
  22738.     if @force_flag = 1
  22739.         begin
  22740.         -- don't qualify that must be publisher when we are forcing remake at subscribers
  22741.         select @pubid = pubid, @snapshot_ready=snapshot_ready from sysmergepublications where name = @publication and 
  22742.             pubid in (select pubid from sysmergearticles where name=@article)
  22743.         end
  22744.     else
  22745.         select @pubid = pubid, @snapshot_ready=snapshot_ready 
  22746.             from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  22747.     if @pubid IS NULL
  22748.         BEGIN
  22749.             RAISERROR (20026, 16, -1, @publication)
  22750.             RETURN (1)
  22751.         END
  22752.  
  22753.     select @conflict_table=NULL
  22754.     select @artid = artid, @objid = objid, @sync_objid = sync_objid, @conflict_table=conflict_table FROM sysmergearticles WHERE name = @article    AND pubid = @pubid
  22755.     if @artid IS NULL
  22756.         BEGIN
  22757.             RAISERROR (20027, 16, -1, @article)
  22758.             RETURN (1)
  22759.         END
  22760.  
  22761.     /* Drop the article procs if they preexist */
  22762.     exec @retcode = dbo.sp_MSdroparticleprocs @pubid, @artid
  22763.     if @@ERROR<>0 OR @retcode<>0 
  22764.         begin
  22765.             return (1)
  22766.         end
  22767.     
  22768.     -- get owner name, and table name
  22769.     select @objectname = name, @ownername = user_name(uid)    from sysobjects
  22770.         where id = @objid 
  22771.  
  22772.     -- make the insert and update proc names
  22773.     exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
  22774.     if @@ERROR <>0 OR @retcode <>0 return (1)
  22775.  
  22776.     exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  22777.     if @@ERROR <>0 OR @retcode <>0 return (1)
  22778.  
  22779.     select @ins_procname = 'sp_ins_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22780.     exec dbo.sp_MSuniqueobjectname @ins_procname, @ins_procname output
  22781.     if @@ERROR <>0 OR @retcode <>0 return (1)
  22782.     
  22783.     select @upd_procname = 'sp_upd_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22784.     exec dbo.sp_MSuniqueobjectname @upd_procname, @upd_procname output
  22785.     if @@ERROR <>0 OR @retcode <>0 return (1)
  22786.  
  22787.     select @sel_procname = 'sp_sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22788.     exec dbo.sp_MSuniqueobjectname @sel_procname, @sel_procname output
  22789.     if @@ERROR <>0 OR @retcode <>0 return (1)
  22790.  
  22791.     set @view_selprocname = 'sel_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22792.     exec @retcode = dbo.sp_MSuniqueobjectname @view_selprocname , @view_selprocname output
  22793.     if @retcode <> 0 or @@ERROR <> 0 return (1) 
  22794.  
  22795.     -- create the procs
  22796.     set @dbname = db_name()
  22797.  
  22798.     set @command = 'sp_MSmakeinsertproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @ins_procname  + ', [' + convert(nchar(36), @pubid) + ']'
  22799.  
  22800.     exec @retcode = master..xp_execresultset @command, @dbname
  22801.  
  22802.     if @@ERROR<>0 OR @retcode<>0 
  22803.         begin
  22804.             return (1)
  22805.         end
  22806.  
  22807.  
  22808.     exec @retcode = dbo.sp_MS_marksystemobject  @ins_procname 
  22809.     if @@ERROR<>0 or @retcode<>0  return (1)
  22810.     
  22811.     exec ('grant exec on ' + @ins_procname + ' to public')
  22812.     set @command = 'sp_MSmakeupdateproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @upd_procname + ', [' + convert(nchar(36), @pubid) + ']'
  22813.     exec @retcode = master..xp_execresultset @command, @dbname
  22814.     if @@ERROR<>0 OR @retcode<>0 
  22815.         begin
  22816.             return (1)
  22817.         end
  22818.     exec @retcode = dbo.sp_MS_marksystemobject  @upd_procname 
  22819.     if @@ERROR<>0 or @retcode<>0 return (1)
  22820.     exec ('grant exec on ' + @upd_procname + ' to public')
  22821.     if @@ERROR<>0 return (1)
  22822.     set @command= 'SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON'
  22823.     exec (@command)
  22824.     if @@ERROR<>0 return (1)
  22825.     set @command = 'sp_MSmakeselectproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername)+ ' , ' + @sel_procname + ', [' + convert(nchar(36), @pubid) + ']'
  22826.     exec @retcode = master..xp_execresultset @command, @dbname
  22827.     if @@ERROR<>0 or @retcode<>0
  22828.         begin
  22829.             return (1)
  22830.         end
  22831.     exec @retcode = dbo.sp_MS_marksystemobject  @sel_procname 
  22832.     if @@ERROR<>0 or @retcode<>0 return (1)
  22833.     exec ('grant exec on ' + @sel_procname + ' to public')
  22834.     if @@ERROR<>0 return (1)
  22835.  
  22836.     if @sync_objid <> 0 
  22837.         begin
  22838.  
  22839.             select @ownername = user_name(uid), @viewname = name from sysobjects 
  22840.                 where id = @sync_objid 
  22841.         select @rgcol = QUOTENAME(name) from syscolumns where id = @objid and
  22842.                 ColumnProperty(id, name, 'isrowguidcol') = 1
  22843.         
  22844.         exec @retcode=dbo.sp_MSmakeviewproc @viewname, @ownername, @view_selprocname, @rgcol, @objid
  22845.         if @@ERROR<>0 or @retcode<>0
  22846.             return (1)
  22847.         end
  22848.     else
  22849.         set @view_selprocname = ''
  22850.  
  22851.     --to be consistent with upgrade code by checking snapshot_ready>0
  22852.     if @snapshot_ready>0 and @conflict_table is not NULl
  22853.         begin
  22854.             exec @retcode = dbo.sp_MSguidtostr @artid, @guidstr out
  22855.             if @@ERROR <>0 OR @retcode <>0 return (1)
  22856.  
  22857.             exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  22858.             if @@ERROR <>0 OR @retcode <>0 return (1)
  22859.  
  22860.             select @conflict_proc = 'sp_cft_' + substring(@guidstr, 1, 16) + substring(@pubidstr, 1, 16)
  22861.  
  22862.             exec @retcode=sp_MSuniqueobjectname @conflict_proc , @conflict_proc output
  22863.             if @@ERROR <> 0 OR @retcode <> 0 
  22864.                 return(1)
  22865.             set @dbname = db_name()
  22866.             set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , ' + QUOTENAME(@ownername) + ' , ' + @conflict_proc  + ' , ' + convert(nvarchar,@objid) 
  22867.  
  22868.             set @command = @command    + ', [' + convert(nchar(36), @pubid) + ']'
  22869.             exec @retcode = master..xp_execresultset @command, @dbname
  22870.             if @@ERROR<>0 OR @retcode<>0 
  22871.             begin
  22872.                 return (1)
  22873.             end
  22874.             exec @retcode = dbo.sp_MS_marksystemobject  @conflict_proc 
  22875.             if @@ERROR<>0 or @retcode<>0  return (1)
  22876.  
  22877.             exec ('grant exec on ' + @conflict_proc + ' to public')
  22878.             if @@ERROR<>0 return (1)
  22879.             update sysmergearticles set ins_conflict_proc = @conflict_proc where artid = @artid and pubid=@pubid
  22880.         end
  22881.     -- update articles to set the names
  22882.     update sysmergearticles set insert_proc = @ins_procname, update_proc = @upd_procname ,
  22883.         select_proc = @sel_procname, view_sel_proc = @view_selprocname
  22884.         where artid = @artid and pubid = @pubid
  22885.     IF @@ERROR<>0 return (1)
  22886.     return (0)
  22887. go
  22888. exec dbo.sp_MS_marksystemobject sp_MSsetartprocs
  22889. go
  22890. grant exec on dbo.sp_MSsetartprocs to public
  22891. go
  22892. SET ANSI_NULLS OFF 
  22893. GO
  22894. raiserror('Creating procedure sp_MSmakesystableviews', 0,1)
  22895. GO
  22896.  
  22897. -- Used by snapshot
  22898. create procedure sp_MSmakesystableviews (
  22899.     @publication sysname,
  22900.     @dynamic_snapshot_views_table_name sysname = null
  22901.     )
  22902. AS
  22903.     declare @guidstr         nvarchar(40)
  22904.     declare @pubid          uniqueidentifier
  22905.     declare @contentsview     sysname 
  22906.     declare @tombstoneview     sysname
  22907.     declare @genhistoryview    sysname
  22908.     declare @filtersview    sysname
  22909.     declare @piece            nvarchar(4000)
  22910.     declare @retcode smallint
  22911.     declare @dbname            sysname
  22912.     declare @art_count        int
  22913.     declare @skip_ctsv         int
  22914.     declare    @command        nvarchar(500)
  22915.     declare @dynamic_filters bit
  22916.     declare @view_creation_command nvarchar(4000)
  22917.     declare @newid          uniqueidentifier
  22918.  
  22919.     /*
  22920.     ** Check to see if current publication has permission
  22921.     */
  22922.     exec @retcode=sp_MSreplcheck_publish
  22923.     if @retcode<>0 or @@ERROR<>0 return (1)
  22924.     set @skip_ctsv = 0
  22925.     select @pubid = pubid, @dynamic_filters = dynamic_filters from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  22926.     if @pubid is null
  22927.         BEGIN
  22928.             RAISERROR (20026, 16, -1, @publication)
  22929.             RETURN (1)
  22930.         END
  22931.     select @art_count=count(*) from sysmergearticles where pubid=@pubid
  22932.     if @art_count > 253
  22933.         set @skip_ctsv=1
  22934.     select @newid = newid()
  22935.     create table #temp_table_for_systable_view(contentsview sysname, tombstoneview sysname NULL, genhistoryview sysname NULL, filtersview sysname NULL)
  22936.     exec @retcode = dbo.sp_MSguidtostr @newid, @guidstr out
  22937.     if @@ERROR<>0 OR @retcode<>0 return (1)
  22938.     select @contentsview = 'cont' + @guidstr
  22939.     select @tombstoneview = 'ts' + @guidstr
  22940.     select @genhistoryview = 'gh' + @guidstr
  22941.     select @filtersview = 'filt' + @guidstr
  22942.  
  22943.     set @guidstr = '''' + convert(nchar(36), @pubid) + ''''
  22944.     
  22945.     exec @retcode = dbo.sp_MSuniqueobjectname @tombstoneview, @tombstoneview out
  22946.     if @@ERROR<>0 OR @retcode<>0 return (1)
  22947.     exec @retcode = dbo.sp_MSuniqueobjectname @contentsview, @contentsview out
  22948.     if @@ERROR<>0 OR @retcode<>0 return (1)
  22949.     exec @retcode = dbo.sp_MSuniqueobjectname @genhistoryview, @genhistoryview out
  22950.     if @@ERROR<>0 OR @retcode<>0 return (1)
  22951.     exec @retcode = dbo.sp_MSuniqueobjectname @filtersview, @filtersview out
  22952.     if @@ERROR<>0 OR @retcode<>0 return (1)
  22953.     
  22954.     insert #temp_table_for_systable_view values(@contentsview,@tombstoneview,@genhistoryview,@filtersview)
  22955.  
  22956.     if @skip_ctsv = 0
  22957.     begin
  22958.         /* generate view for MSmerge_contents qualified by the pubid */
  22959.         /* For dynamically filtered publication, security check is performed in
  22960.            the sync view of the base table */
  22961.         set @command = 'sp_MSmakectsview ' + QUOTENAME(@publication) + ' , ' + @contentsview + ' , ' + COALESCE(QUOTENAME(@dynamic_snapshot_views_table_name) collate database_default, N'null' collate database_default) 
  22962.         set @dbname = db_name()
  22963.  
  22964.         exec @retcode = master..xp_execresultset @command, @dbname
  22965.         if @@ERROR<>0 OR @retcode <>0 
  22966.             return (1)
  22967.     end
  22968.     else
  22969.     begin
  22970.         exec('create view ' + @contentsview + ' as select * from MSmerge_contents where 1 = 2')
  22971.         if @@ERROR<>0
  22972.             return (1)
  22973.     end
  22974.     /* 
  22975.     ** generate the view for dbo.MSmerge_tombstone. In SP2 and Shiloh, the change was made to make the view 
  22976.     ** return 0 rows since it is unnecessary and expensive to propagate the tombstones.
  22977.     ** In order to leave all the other moving parts unchanged, we decided to let the view 
  22978.     ** return 0 rows.
  22979.     */
  22980.     select @view_creation_command = 'create view ' + @tombstoneview + ' as select * from dbo.MSmerge_tombstone where 1= 2 and
  22981.             tablenick in (select nickname from sysmergearticles where pubid = ' +
  22982.             @guidstr + ')'
  22983.  
  22984.     if @dynamic_filters = 1
  22985.     begin
  22986.         select @view_creation_command = @view_creation_command + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  22987.     end
  22988.  
  22989.     exec (@view_creation_command)
  22990.     if @@ERROR <>0 
  22991.         begin
  22992.             return (1)
  22993.         end
  22994.  
  22995.     select @view_creation_command = 'create view ' + @genhistoryview + '(guidsrc, guidlocal, pubid, generation,
  22996.             art_nick, nicknames, coldate) as select DISTINCT guidsrc, guidlocal, CONVERT(uniqueidentifier, ' 
  22997.             + @guidstr + '), generation, art_nick, nicknames, coldate  from dbo.MSmerge_genhistory
  22998.             where guidlocal <> ''00000000-0000-0000-0000-000000000000'' and (art_nick = 0 or art_nick is NULL or
  22999.                     art_nick in (select nickname from sysmergearticles where pubid = ' +
  23000.             @guidstr + ')) '
  23001.     if @dynamic_filters = 1
  23002.     begin
  23003.         select @view_creation_command = @view_creation_command + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  23004.     end
  23005.  
  23006.     exec (@view_creation_command)
  23007.     if @@ERROR <>0
  23008.         begin
  23009.             return (1)
  23010.         end
  23011.  
  23012.     select @view_creation_command = 'create view ' + @filtersview + ' as select * from sysmergesubsetfilters where pubid = ' +
  23013.             @guidstr
  23014.  
  23015.     if @dynamic_filters = 1
  23016.     begin
  23017.         select @view_creation_command = @view_creation_command + ' and ((is_srvrolemember(''sysadmin'') = 1) or (is_member(''db_owner'') = 1) or (sessionproperty(''replication_agent'') = 1))'
  23018.     end
  23019.  
  23020.     exec (@view_creation_command)
  23021.     if @@ERROR <>0
  23022.         begin
  23023.             return (1)
  23024.         end
  23025.  
  23026.     if @dynamic_filters = 1
  23027.     begin
  23028.         exec ('grant select on ' + @contentsview + ' to public')
  23029.         if @@error<>0 return(1)
  23030.         exec ('grant select on ' + @tombstoneview + ' to public')
  23031.         if @@error<>0 return(1)
  23032.         exec ('grant select on ' + @genhistoryview + ' to public')
  23033.         if @@error<>0 return(1)
  23034.         exec ('grant select on ' + @filtersview + ' to public')            
  23035.         if @@error<>0 return(1)
  23036.     end
  23037.  
  23038.     set nocount on
  23039.     /* we only generate per-article contents view for static publications */
  23040.     if @dynamic_filters=0
  23041.         begin
  23042.             exec @retcode = sp_MSgettablecontents @pubid
  23043.             if @@ERROR<>0 OR @retcode <>0 return (1)
  23044.          end
  23045.     exec('select * from #temp_table_for_systable_view ')
  23046.     drop table #temp_table_for_systable_view
  23047.  
  23048.     return (0)
  23049. go
  23050. exec dbo.sp_MS_marksystemobject sp_MSmakesystableviews
  23051. go
  23052. grant exec on dbo.sp_MSmakesystableviews to public
  23053. go
  23054.  
  23055.  
  23056. raiserror('Creating procedure sp_MSgetchangecount', 0,1)
  23057. GO
  23058.  
  23059. create procedure sp_MSgetchangecount(
  23060.     @startgen     int,
  23061.      @changes     int output,
  23062.      @updates     int output,
  23063.      @deletes     int output) as
  23064.     
  23065.     
  23066.     select @deletes = count(*) from dbo.MSmerge_tombstone where generation = 0 or generation > @startgen
  23067.     select @updates = count(*) from dbo.MSmerge_contents where generation = 0 or generation > @startgen
  23068.     select @changes = @updates + @deletes
  23069.     return (0)        
  23070. go
  23071.  
  23072. exec dbo.sp_MS_marksystemobject sp_MSgetchangecount
  23073. go
  23074. grant exec on dbo.sp_MSgetchangecount to public
  23075.  
  23076. raiserror('Creating procedure sp_MSbelongs', 0,1)
  23077. GO
  23078.  
  23079. -- Modify temp table. No security check needed.
  23080. create procedure sp_MSbelongs
  23081.     @publisher        sysname,
  23082.     @publisher_db    sysname,
  23083.     @publication     sysname,
  23084.     @tablenick        int,
  23085.     @rowguid        uniqueidentifier,
  23086.     @retval            int output,
  23087.     @nested         int = 0
  23088. AS
  23089.     declare @artid uniqueidentifier
  23090.     declare @join_guid uniqueidentifier
  23091.     declare @last_joinid int
  23092.     declare @join_id int
  23093.     declare @join_nick int
  23094.     declare @probe_id int
  23095.     declare @last_probe int
  23096.     declare @join_nickstr nvarchar(10)
  23097.     declare @pubid uniqueidentifier
  23098.     declare @guidstring nvarchar(38)
  23099.     declare @subset_filter nvarchar(4000)
  23100.     declare @tablename nvarchar(266)
  23101.     declare @join_table nvarchar(266)
  23102.     declare @boolean nvarchar(4000)
  23103.     declare @retcode smallint
  23104.     
  23105.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  23106.  
  23107.     /* Check for case of all rows  - do I trust subset_type ? */
  23108.     select @boolean = subset_filterclause, @artid = artid from sysmergearticles where
  23109.         pubid = @pubid and nickname = @tablenick
  23110.  
  23111.     if ((@boolean is null or @boolean = ' ') and not exists
  23112.         (select * from sysmergesubsetfilters where art_nickname = @tablenick))
  23113.         begin
  23114.         set @retval = 0
  23115.         return
  23116.         end
  23117.     if @nested = 0
  23118.         begin
  23119.         create table #found (flag int NOT NULL)
  23120.         create table #probe (probe_id int identity NOT NULL, tablenick int NOT NULL, 
  23121.                 rowguid uniqueidentifier ROWGUIDCOL default newid() not null, tested int NOT NULL)
  23122.         insert into #found values (0)
  23123.         set @last_probe = 0
  23124.         end
  23125.     else
  23126.         begin
  23127.         select @last_probe = max(probe_id) from #probe
  23128.         end
  23129.  
  23130.     /* pubid is already available */
  23131.     
  23132.     exec @retcode = dbo.sp_MStablenamefromnick @tablenick, @tablename out, @pubid
  23133.  
  23134.     if  @@ERROR<>0 or @retcode<>0 return (1) 
  23135.     set @guidstring = '''' + convert(nchar(36), @rowguid) + ''''
  23136.  
  23137.     /* If there is boolean filter, check for it being satisfied */
  23138.     if @boolean is not null and @boolean <> ' '
  23139.         begin
  23140.         exec ('if exists (select * from ' + @tablename + ' where rowguidcol = ' +
  23141.             @guidstring + ' and (' + @boolean + ')) update #found set flag = 1')
  23142.         if @@ERROR<>0 return (1)
  23143.         select @retval = flag from #found
  23144.         if @retval = 1 goto EndLabel
  23145.         end
  23146.     
  23147.     /* Loop over join filters, populating #probe */
  23148.     select @join_id = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and art_nickname = @tablenick
  23149.     while @join_id is not null
  23150.         begin
  23151.         select @boolean = join_filterclause, @join_nick = join_nickname from sysmergesubsetfilters where pubid = @pubid and join_filterid = @join_id
  23152.         exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @join_table out, @pubid
  23153.         if @@ERROR<>0 or @retcode<>0 return (1)
  23154.         set @join_nickstr = convert(nchar(10), @join_nick)
  23155.  
  23156.         /* execute a query to put these into the #probe table */
  23157.         exec ('insert into #probe (tablenick, rowguid, tested) select distinct ' + @join_nickstr + 
  23158.             ', ' + @join_table + '.rowguidcol, 0 from ' + @tablename + ', ' + @join_table + '   
  23159.             where ' + @tablename + '.rowguidcol = ' + @guidstring + ' and (' + @boolean + ')
  23160.             and not exists (select * from #probe where tablenick = ' + @join_nickstr + 
  23161.             ' and rowguidcol = ' + @join_table + '.rowguidcol) ' )
  23162.         if @@ERROR<>0 
  23163.             begin
  23164.                 return (1)
  23165.             end    
  23166.  
  23167.         /* get to next join filter and repeat */
  23168.         set @last_joinid = @join_id
  23169.         select @join_id = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and art_nickname = @tablenick and join_filterid > @last_joinid
  23170.         end
  23171.     /* Loop over probe, making recursive call */
  23172.     select @probe_id = min(probe_id) from #probe where probe_id > @last_probe and tested = 0
  23173.     while @probe_id is not null
  23174.         begin
  23175.         select @join_nick = tablenick, @join_guid = rowguidcol from #probe where probe_id = @probe_id
  23176.         set @last_probe = @probe_id
  23177.  
  23178.         /* update tested flag on this row so we don't try it again while recursing */
  23179.         update #probe set tested = 1 where probe_id = @probe_id
  23180.     
  23181.         /* Make recursive call. If it belongs, we are done. */
  23182.         exec @retcode = dbo.sp_MSbelongs @publisher, @publisher_db, @publication, @join_nick, @join_guid, @retval output, 1
  23183.         if @@ERROR<>0 OR @retcode<>0
  23184.             begin
  23185.                 return (1)
  23186.             end
  23187.  
  23188.         if @retval = 1 goto EndLabel
  23189.         /* get next probe_id and repeat */
  23190.         select @probe_id = min(probe_id) from #probe where probe_id > @last_probe and tested = 0
  23191.         end
  23192.  
  23193.     /* All Done, delete temps if not nested */
  23194. EndLabel:
  23195.     if @nested = 0
  23196.         begin
  23197.         drop table #found
  23198.         drop table #probe
  23199.         end
  23200.     return
  23201.  
  23202. go
  23203.  
  23204. exec dbo.sp_MS_marksystemobject sp_MSbelongs
  23205. go
  23206. grant exec on dbo.sp_MSbelongs to public
  23207. go
  23208.  
  23209. raiserror('Creating procedure sp_MSexpandbelongs', 0,1)
  23210. GO
  23211.  
  23212. -- Modify temp table. No security check needed.
  23213. create procedure sp_MSexpandbelongs
  23214.     @pubid         uniqueidentifier
  23215. AS
  23216.     declare @filterid int
  23217.     declare @retval            int
  23218.     declare @expand_proc    sysname
  23219.     
  23220.     /* We iterate over the join filters */
  23221.     --select @filterid = min(flag) from #belong
  23222.     select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and
  23223.             exists (select * from #belong where tablenick = join_nickname and flag < join_filterid and skipexpand = 0)
  23224.     while (@filterid is not null)
  23225.         begin
  23226.         select @expand_proc = expand_proc from sysmergesubsetfilters where pubid = @pubid and
  23227.                 join_filterid = @filterid
  23228.         exec @retval = @expand_proc @belong = 1
  23229.         if @@error<>0 or @retval <> 0 return (1)
  23230.         select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and
  23231.             exists (select * from #belong where tablenick = join_nickname and flag < join_filterid and skipexpand = 0)
  23232.         end
  23233.         
  23234.     return (0)
  23235. go
  23236. exec dbo.sp_MS_marksystemobject sp_MSexpandbelongs
  23237. go
  23238. grant exec on dbo.sp_MSexpandbelongs to public
  23239. go
  23240.  
  23241. raiserror('Creating procedure sp_MSexpandnotbelongs', 0,1)
  23242. GO
  23243.  
  23244. -- Modify temp table. No security check needed.
  23245. create procedure sp_MSexpandnotbelongs
  23246.     @pubid         uniqueidentifier
  23247. AS
  23248.     declare @filterid         int
  23249.     declare @retval            int
  23250.     declare @expand_proc    sysname
  23251.     
  23252.     /* We iterate over the join filters */
  23253.     --select @filterid = min(flag) from #notbelong
  23254.     select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and
  23255.             exists (select * from #notbelong where tablenick = join_nickname and flag < join_filterid)
  23256.     while (@filterid is not null)
  23257.         begin
  23258.         select @expand_proc = expand_proc from sysmergesubsetfilters where pubid = @pubid and
  23259.                 join_filterid = @filterid
  23260.         exec @retval = @expand_proc @belong = 0
  23261.         if @@error<>0 or @retval <> 0 return (1)
  23262.         select @filterid = min(join_filterid) from sysmergesubsetfilters where pubid = @pubid and
  23263.             exists (select * from #notbelong where tablenick = join_nickname and flag < join_filterid)
  23264.         end
  23265.  
  23266.  
  23267. go
  23268.  
  23269. exec dbo.sp_MS_marksystemobject sp_MSexpandnotbelongs
  23270. go
  23271. grant exec on dbo.sp_MSexpandnotbelongs to public
  23272. go
  23273.  
  23274. raiserror('Creating procedure sp_MSsetupbelongs_withoutviewproc', 0,1)
  23275. GO
  23276. create procedure sp_MSsetupbelongs_withoutviewproc
  23277.     @publisher            sysname,
  23278.     @publisher_db        sysname,
  23279.     @publication         sysname,
  23280.     @artnick            int
  23281. AS
  23282.     declare @temp_id int
  23283.     declare @artnickstr nvarchar(10)
  23284.     declare @retval int
  23285.     declare @tablenick int
  23286.     declare @rowguid uniqueidentifier
  23287.     declare @rowguidstr nvarchar(40)
  23288.     declare @partchangegen int
  23289.     declare @joinchangegen int
  23290.     declare @retcode smallint
  23291.     
  23292.     set @artnickstr = convert(nchar(10), @artnick)
  23293.  
  23294.     delete from #temp_cont
  23295.  
  23296.     if exists(select * from #genlist)
  23297.     begin
  23298.         exec ('insert into #temp_cont (tablenick, rowguid, partchangegen, joinchangegen) 
  23299.                 select tablenick, rowguid, partchangegen, joinchangegen from dbo.MSmerge_contents where
  23300.                 tablenick  = ' + @artnickstr + ' and generation in (select generation from #genlist)')
  23301.         if @@ERROR <>0
  23302.         begin
  23303.             return (1)
  23304.         end    
  23305.     end
  23306.     
  23307.     set @temp_id = 0
  23308.     select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
  23309.     while (@temp_id is not null)
  23310.     begin
  23311.         select    @tablenick = tablenick, @rowguid = rowguid,
  23312.                 @partchangegen = partchangegen, @joinchangegen = joinchangegen 
  23313.                 from #temp_cont where temp_id = @temp_id
  23314.         set @rowguidstr = '''' + convert(nchar(36), @rowguid) + ''''
  23315.         exec @retcode = dbo.sp_MSbelongs @publisher, @publisher_db,    @publication, @tablenick, @rowguid, @retval    output, 0
  23316.         if @@ERROR<>0 OR @retcode <>0
  23317.         begin
  23318.             return (1)
  23319.         end
  23320.  
  23321.         if @retval = 1
  23322.         begin
  23323.             insert into #belong (tablenick, rowguid, flag, skipexpand, partchangegen, joinchangegen) values
  23324.                     (@artnick, @rowguid, 0, 0, @partchangegen, @joinchangegen)
  23325.             if @@ERROR <>0 
  23326.             begin
  23327.                 return (1)
  23328.             end
  23329.         end
  23330.         select @temp_id = min(temp_id) from #temp_cont where temp_id > @temp_id
  23331.     end
  23332.  
  23333.     return 0
  23334. GO
  23335. exec dbo.sp_MS_marksystemobject sp_MSsetupbelongs_withoutviewproc
  23336. go
  23337. grant exec on dbo.sp_MSsetupbelongs_withoutviewproc to public
  23338. go
  23339. raiserror('Creating procedure sp_MSsetupnotbelongs', 0,1)
  23340. GO
  23341. create procedure sp_MSsetupnotbelongs
  23342. @artnick            int,
  23343. @before_view_objid    int,
  23344. @before_table_objid int,
  23345. @rgcol                sysname,
  23346. @commongen            int
  23347. AS
  23348.     declare @before_view_name sysname
  23349.     declare @before_table_name sysname
  23350.     declare @artnickstr nvarchar(10)
  23351.     declare @commongenstr nvarchar(12)
  23352.     
  23353.     set @artnickstr = convert(nvarchar(10), @artnick)
  23354.     set @commongenstr = convert(nvarchar(12), @commongen)
  23355.     
  23356.     /* Put changes in #notbelong  that aren't in #belong and have a relevant partchangegen    */
  23357.     -- If publication has before image tables, we should screen changes using the before image tables
  23358.     --rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ') and
  23359.     if @before_view_objid is not null
  23360.     begin
  23361.         set @before_view_name = OBJECT_NAME(@before_view_objid)
  23362.         set @before_table_name = OBJECT_NAME(@before_table_objid)
  23363.         execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen)
  23364.                 select tablenick, rowguid, 0, partchangegen, joinchangegen
  23365.                 from #contents_subset
  23366.                 where partchangegen > ' + @commongenstr + ' 
  23367.                 and tablenick = ' + @artnickstr + ' 
  23368.                 and    (rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ' where generation > ' + @commongenstr + ')
  23369.                 or (rowguid in (select ' + @rgcol + '  from ' + @before_table_name + ' where system_delete = 1 and generation > ' + @commongenstr + ')
  23370.                 and (rowguid not in (select ' + @rgcol + ' from ' + @before_view_name + ' where generation > ' + @commongenstr + '))))    
  23371.                 and rowguid not in (select rowguid from #belong) ')
  23372.         if @@ERROR <>0 
  23373.         begin
  23374.             return (1)
  23375.         end
  23376.             
  23377.         if exists (select * from #genlist)
  23378.         begin
  23379.             /* Add tombstones to ##notbelong */
  23380.             execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) 
  23381.                 select tablenick, rowguid,  0, generation, generation, type from
  23382.                 #tombstone_subset where tablenick = ' + @artnickstr + ' and
  23383.                 (type = 6 or rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ' where generation > ' + @commongenstr + '))')
  23384.             if @@ERROR <>0
  23385.             begin
  23386.                 return (1)
  23387.             end
  23388.         end
  23389.     end
  23390.     else
  23391.     begin 
  23392.         insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen)
  23393.             select tablenick, rowguid, 0, partchangegen, joinchangegen
  23394.                 from #contents_subset
  23395.                 where partchangegen > @commongen 
  23396.                 and tablenick = @artnick 
  23397.                 and rowguid not in (select rowguid from #belong)
  23398.  
  23399.         if @@ERROR <>0
  23400.         begin
  23401.             return (1)
  23402.         end
  23403.  
  23404.         if exists (select * from #genlist)
  23405.         begin
  23406.             insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) 
  23407.                 select tablenick, rowguid,  0, generation, generation, type from
  23408.                 #tombstone_subset where tablenick = @artnick
  23409.  
  23410.             if @@ERROR <>0
  23411.             begin
  23412.                 return (1)
  23413.             end
  23414.         end
  23415.     end
  23416.  
  23417.     return (0)
  23418. GO
  23419. exec dbo.sp_MS_marksystemobject sp_MSsetupnotbelongs
  23420. go
  23421. grant exec on dbo.sp_MSsetupnotbelongs to public
  23422. go
  23423.  
  23424. raiserror('Creating procedure sp_MSsetupworktables', 0,1)
  23425. GO
  23426.  
  23427. -- Modify temp table. No security check needed.
  23428. create procedure sp_MSsetupworktables
  23429.     @pubid                uniqueidentifier,
  23430.     @genlist             varchar(8000),
  23431.     @articlesoption        int,    -- 0=process all articles, 1=process this specific article (whose nickname is passed in @tablenickname), 2=all articles involved in join filters, 3=process all articles involved in part filters, 4=process articles whose nicknames have been passed in @nicknamelist.
  23432.     @tablenickname        int,
  23433.     @nicknamelist        varchar(8000),
  23434.     @mingen                int = 0,
  23435.     @maxgen                int = 0,
  23436.     @skipgenlist        varchar(8000) = NULL,
  23437.     @contents_subset_rowcount int OUTPUT,
  23438.     @tombstone_subset_rowcount int OUTPUT
  23439. AS
  23440.     
  23441.     declare @lengenlist int
  23442.     declare @lenskipgenlist int
  23443.  
  23444.     -- put in a nickname with value 0 - This will match 
  23445.     -- gen history rows put in by downlevel subscribers 
  23446.     -- with art_nick = NULL 
  23447.     insert into #nicknames_to_process values (0)
  23448.  
  23449.     if (@articlesoption = 0)
  23450.     begin
  23451.         
  23452.         -- process all articles for this publication
  23453.         insert into #nicknames_to_process 
  23454.         select distinct nickname 
  23455.         from sysmergearticles a 
  23456.         where pubid = @pubid
  23457.  
  23458.     end
  23459.     else if (@articlesoption = 1)
  23460.     begin
  23461.         
  23462.         --process only the article whose nickname has been passed-in
  23463.         insert into #nicknames_to_process values (@tablenickname)
  23464.         
  23465.     end
  23466.     else if (@articlesoption = 2)
  23467.     begin
  23468.         --process all articles with join filters (article could be on any side - left or right - of any join filter)
  23469.         insert into #nicknames_to_process 
  23470.         select distinct nickname 
  23471.         from sysmergearticles a 
  23472.         where pubid = @pubid 
  23473.         and exists (select * from sysmergesubsetfilters s 
  23474.                     where s.pubid = @pubid 
  23475.                     and (s.art_nickname = a.nickname or s.join_nickname = a.nickname))
  23476.     end
  23477.     else if (@articlesoption = 3)
  23478.     begin
  23479.     
  23480.         --process all articles with part filters but that don't have a join filter.
  23481.         insert into #nicknames_to_process 
  23482.         select distinct nickname 
  23483.         from sysmergearticles a 
  23484.         where pubid = @pubid 
  23485.         and datalength(subset_filterclause) > 1
  23486.         and not exists (select * from sysmergesubsetfilters s 
  23487.                     where s.pubid = @pubid 
  23488.                     and (s.art_nickname = a.nickname or s.join_nickname = a.nickname))
  23489.     end
  23490.     else if (@articlesoption = 4)
  23491.     begin
  23492.         --process all articles whose nicknames have been passed into @nicknamelist
  23493.         if (@nicknamelist is not null and rtrim(ltrim(@nicknamelist)) <> '')
  23494.         begin
  23495.             exec ('insert into #nicknames_to_process select distinct nickname from sysmergearticles where nickname in (' + @nicknamelist + ')')
  23496.             if @@ERROR <>0 return (1)
  23497.         end
  23498.     end
  23499.  
  23500.     -- Create index on #nicknames_to_process now that it has been populated. Creating it after data insertion is better because
  23501.     -- that generates the stats for the index. That helps in the insert into #contents_subset query. The other option was to 
  23502.     -- create the index, insert the data, and then update statistics.
  23503.     create unique index #nicknames_ind on #nicknames_to_process (nickname)
  23504.  
  23505.     if (@maxgen <> 0)
  23506.     begin
  23507.             
  23508.         insert into #genlist select distinct generation 
  23509.             from dbo.MSmerge_genhistory gh 
  23510.             join #nicknames_to_process np
  23511.             on isnull(gh.art_nick,0) = np.nickname and 
  23512.             gh.generation >= @mingen
  23513.             and gh.generation <= @maxgen
  23514.  
  23515.         select @lengenlist = isnull(datalength(@genlist),0)
  23516.         select @lenskipgenlist = isnull(datalength(@skipgenlist),0)
  23517.  
  23518.         -- no need to do ltrim and rtrim on the @skipgenlist. sp_MSsetupbelongs already did that.
  23519.         if (@skipgenlist is not null and @skipgenlist <> '' and @lenskipgenlist <= @lengenlist)
  23520.         begin
  23521.             exec('delete from #genlist where generation in (' + @skipgenlist + ')')
  23522.         end
  23523.         else if (@genlist is not null and @genlist <> '')
  23524.         begin
  23525.             -- gen 0 won't be in @genlist, so will get deleted because of the NOT IN.
  23526.             exec('delete from #genlist where generation not in (' + @genlist + ')')
  23527.         end
  23528.     end
  23529.     else if (@genlist is not null and @genlist <> '')
  23530.     begin
  23531.         exec ('insert into #genlist select distinct generation from dbo.MSmerge_genhistory where
  23532.             (isnull(art_nick,0) in (select nickname from #nicknames_to_process)) and 
  23533.             generation in (' + @genlist + ') ')
  23534.         if @@ERROR <>0 return (1)
  23535.     end
  23536.  
  23537.     -- Create index on #genlist now that it has been populated. Creating it after data insertion is better because
  23538.     -- that generates the stats for the index. That helps in the insert into #contents_subset query. The other option was to 
  23539.     -- create the index, insert the data, and then update statistics.
  23540.     create unique index #genlist_ind on #genlist (generation)
  23541.  
  23542.     if @maxgen is null
  23543.         select @maxgen = 0
  23544.  
  23545.     if @mingen is null
  23546.         select @mingen = 0
  23547.  
  23548.     if (@maxgen = 0)
  23549.     begin
  23550.         -- SQL 7.0 pull merge agents do not pass in @maxgen and @mingen, so the default is 0. 
  23551.         -- For them need to compute min and max. Note that we could do the same for 8.0 agents as well
  23552.         -- but 8.0 agents pass the min and max because they are used in the INSERT INTO #genlist query above
  23553.         -- when we don't have the #genlist table and all we have is the comma-separated @genlist string.
  23554.         select @mingen = min(generation), @maxgen = max(generation) from #genlist
  23555.     end
  23556.  
  23557.     insert into #contents_subset (tablenick, rowguid, generation, partchangegen, joinchangegen) 
  23558.     select c.tablenick, c.rowguid, c.generation, c.partchangegen, c.joinchangegen
  23559.     from dbo.MSmerge_contents c 
  23560.     JOIN #nicknames_to_process a
  23561.     ON c.generation >= @mingen
  23562.     AND c.generation <= @maxgen
  23563.     AND c.tablenick = a.nickname
  23564.     JOIN #genlist g 
  23565.     ON c.generation = g.generation
  23566.     AND c.generation >= @mingen
  23567.     AND c.generation <= @maxgen
  23568.  
  23569.     UNION
  23570.     
  23571.     -- the rows retrieved below have a partition change that falls into the relevant generation range
  23572.     -- if we do not process them now, we would later on assume that the partition change has already been processed
  23573.     select c.tablenick, c.rowguid, c.generation, c.partchangegen, c.joinchangegen
  23574.     from dbo.MSmerge_contents c 
  23575.     JOIN #nicknames_to_process a
  23576.     ON c.partchangegen >= @mingen
  23577.     AND c.partchangegen <= @maxgen
  23578.     AND c.tablenick = a.nickname
  23579.     JOIN #genlist g 
  23580.     ON c.partchangegen = g.generation
  23581.     AND c.partchangegen >= @mingen
  23582.     AND c.partchangegen <= @maxgen
  23583.     
  23584.     select @contents_subset_rowcount = @@rowcount
  23585.  
  23586.     insert into #tombstone_subset (tablenick, rowguid, type, generation)
  23587.     select t.tablenick, t.rowguid, t.type, t.generation
  23588.     from dbo.MSmerge_tombstone t
  23589.     JOIN #nicknames_to_process a
  23590.     ON t.generation >= @mingen
  23591.     AND t.generation <= @maxgen
  23592.     AND t.tablenick = a.nickname
  23593.     JOIN #genlist g
  23594.     ON t.generation = g.generation
  23595.     AND t.generation >= @mingen
  23596.     AND t.generation <= @maxgen
  23597.         
  23598.     select @tombstone_subset_rowcount = @@rowcount
  23599.  
  23600.     create clustered index #ucind_contents_subset on #contents_subset (tablenick, rowguid) with FILLFACTOR = 100
  23601.     create clustered index #ucind_tombstone_subset on #tombstone_subset (tablenick, rowguid) with FILLFACTOR = 100
  23602.  
  23603.     delete #nicknames_to_process from #nicknames_to_process ntp
  23604.     where not exists (select tablenick from #contents_subset cs where cs.tablenick = ntp.nickname) 
  23605.     and not exists (select tablenick from #tombstone_subset ts where ts.tablenick = ntp.nickname) 
  23606.  
  23607.     -- remove the nickname with value 0 that we put in specially at the beginning of this proc.
  23608.     delete from #nicknames_to_process where nickname = 0
  23609.     return (0)
  23610. GO
  23611. exec dbo.sp_MS_marksystemobject sp_MSsetupworktables
  23612. go
  23613. grant exec on dbo.sp_MSsetupworktables to public
  23614. go
  23615. raiserror('Creating procedure sp_MSsetupbelongs', 0,1)
  23616. GO
  23617.  
  23618. -- Modify temp table. No security check needed.
  23619. create procedure sp_MSsetupbelongs
  23620.     @publisher            sysname,
  23621.     @publisher_db        sysname,
  23622.     @publication         sysname,
  23623.     @genlist             varchar(8000),
  23624.     @commongen            int,
  23625.     @subissql            int,
  23626.     @articlesoption        int=0,    -- 0=process all articles, 1=process this specific article (whose nickname is passed in @tablenickname), 2=all articles involved in join filters, 3=process all articles involved in part filters, 4=process articles whose nicknames have been passed in @nicknamelist.
  23627.     @tablenickname        int=0,
  23628.     @handle_null_tables bit=0,     -- 0=caller cannot handle NULL ##belongs and ##notbelongs tables, 1=caller handles NULL ##belongs and ##notbelongs tables (post 8.0 Beta 2 version)
  23629.     @nicknamelist        varchar(8000) = NULL,
  23630.     @mingen                int = 0,
  23631.     @maxgen                int = 0,
  23632.     @skipgenlist        varchar(8000) = NULL
  23633.  
  23634. AS
  23635.     declare @pubid uniqueidentifier
  23636.     declare @retval int
  23637.     declare @tablenick int
  23638.     declare @rowguid uniqueidentifier
  23639.     declare @rowguidstr nvarchar(40)
  23640.     declare @belongsname sysname
  23641.     declare @notbelongsname sysname
  23642.     declare @artnick    int
  23643.     declare @before_view_objid int
  23644.     declare @before_table_objid int
  23645.     declare @procname sysname
  23646.     declare @artbaseobjid int
  23647.     declare @rgcol sysname
  23648.     declare @maxfilterid int
  23649.     declare @retcode smallint
  23650.     declare @dynamic_join_cnt int
  23651.     declare @contents_subset_rowcount int
  23652.     declare @tombstone_subset_rowcount int
  23653.     declare @belongsempty bit
  23654.     declare @notbelongsempty bit
  23655.  
  23656.     -- trim spaces from the generation lists so that we don't have to use functions ltrim 
  23657.     -- and rtrim again and again later on.
  23658.     select @genlist = ltrim(rtrim(@genlist))
  23659.     select @skipgenlist = ltrim(rtrim(@skipgenlist))
  23660.     
  23661.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db    
  23662.     
  23663.     set @rowguid = newid()
  23664.     
  23665.     select @rowguidstr = replace( convert( nvarchar(36), @rowguid ), '-', '' )
  23666.  
  23667.     set @belongsname = '##belong' + @rowguidstr
  23668.     set @notbelongsname = '##notbelong' + @rowguidstr
  23669.     -- since the belongsname and notbelongsname names have guids appended to them generated using newid(), we can safely assume
  23670.     -- that the names are unique.
  23671.  
  23672.     create table #genlist (generation int)
  23673.  
  23674.     create table #temp_cont (temp_id int identity NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  23675.             partchangegen int null, joinchangegen int null)
  23676.  
  23677.     create table #contents_subset(tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, generation int NOT NULL,
  23678.             partchangegen int NULL, joinchangegen int NULL)
  23679.     
  23680.     create table #tombstone_subset(tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, type tinyint NOT NULL, 
  23681.             generation int NOT NULL)
  23682.  
  23683.     create table #belong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL,
  23684.         partchangegen int null, joinchangegen int null, skipexpand bit NOT NULL)
  23685.  
  23686.     create table #notbelong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  23687.         flag int NOT NULL, partchangegen int null, joinchangegen int null, type tinyint default 5)
  23688.     create table #nicknames_to_process (nickname int)
  23689.     create index #indbelong on #belong (rowguid, tablenick)
  23690.     create index #indnbelong on #notbelong (tablenick, rowguid)
  23691.  
  23692.     exec ('create table ' + @belongsname + ' (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  23693.         generation int NULL, lineage varbinary(255) NULL, colv varbinary(2048) NULL)')
  23694.     if @@ERROR <>0 return (1)
  23695.         
  23696.     exec ('create table ' + @notbelongsname + ' (bookmark int identity unique NOT NULL, tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL,
  23697.         generation int NULL, lineage varbinary(255) NULL, type tinyint NOT NULL)')
  23698.  
  23699.     if @@ERROR <>0 return (1)
  23700.  
  23701.     -- Fully qualifying the proc avoids recompiles
  23702.     exec @retcode = dbo.sp_MSsetupworktables @pubid, @genlist, @articlesoption, @tablenickname, @nicknamelist,
  23703.                                         @mingen, @maxgen, @skipgenlist,
  23704.                                         @contents_subset_rowcount OUTPUT, @tombstone_subset_rowcount OUTPUT
  23705.  
  23706.     IF @@ERROR<>0 OR @retcode<>0 return (1)    
  23707.  
  23708.     if (@contents_subset_rowcount = 0 and @tombstone_subset_rowcount = 0)
  23709.         goto EXITPROC
  23710.  
  23711.     if (@articlesoption <> 1 and @articlesoption <> 3 and @articlesoption <> 4)
  23712.     begin
  23713.         select @dynamic_join_cnt = count(*) from 
  23714.             (select join_filterclause_spaces_stripped = 
  23715.             REPLACE(REPLACE(REPLACE(REPLACE(UPPER(join_filterclause collate SQL_Latin1_General_CP1_CS_AS), char(0x20),''), char(0x09),''), char(0x0D),''), char(0x0A),'')
  23716.             from sysmergesubsetfilters 
  23717.             where pubid = @pubid) 
  23718.             as sysmergesubsetfilters_temp
  23719.         where 
  23720.         sysmergesubsetfilters_temp.join_filterclause_spaces_stripped like '%USER[_]%NAME()%' or
  23721.         sysmergesubsetfilters_temp.join_filterclause_spaces_stripped like '%USER[_]%ID()%' or
  23722.         sysmergesubsetfilters_temp.join_filterclause_spaces_stripped like '%SESSION[_]USER%' or
  23723.         sysmergesubsetfilters_temp.join_filterclause_spaces_stripped like '%SYSTEM[_]USER%'
  23724.     end
  23725.     
  23726.     /* step 2 setup pass through dbo.MSmerge_contents */
  23727.     /* article with permanent views can be handled with bulk inserts */
  23728.     set @artnick = NULL
  23729.     set rowcount 0
  23730.     
  23731.     /* Get first article, go into loop */
  23732.     select @artnick = min(nickname) from #nicknames_to_process 
  23733.     
  23734.     while (@artnick is not null)
  23735.     begin
  23736.         select    @artbaseobjid = objid, @procname = view_sel_proc, @before_view_objid = before_view_objid,
  23737.                 @before_table_objid = before_image_objid 
  23738.                 from sysmergearticles 
  23739.                 where pubid = @pubid 
  23740.                 and nickname = @artnick
  23741.         /* Get name of rowguidcol. Aliasing doesn't work through a view. */
  23742.         select @rgcol = name from syscolumns where id = @artbaseobjid and ColumnProperty(@artbaseobjid, name, 'isrowguidcol') = 1
  23743.  
  23744.         if (@procname is not null)
  23745.         begin
  23746.             -- Fully qualifying the proc avoids recompiles
  23747.             select @procname = 'dbo.' + @procname
  23748.             exec @retcode = @procname @artnick
  23749.             if @@ERROR <>0 or @retcode <> 0
  23750.                 begin
  23751.                 return (1)
  23752.                 end
  23753.         end
  23754.         else
  23755.         begin
  23756.             -- Fully qualifying the proc avoids recompiles
  23757.             exec @retcode = dbo.sp_MSsetupbelongs_withoutviewproc @publisher, @publisher_db, @publication, @artnick        
  23758.             if @@ERROR <>0 or @retcode <> 0
  23759.                 return (1)
  23760.         end
  23761.  
  23762.         -- Fully qualifying the proc avoids recompiles
  23763.         exec @retcode = dbo.sp_MSsetupnotbelongs @artnick, @before_view_objid, @before_table_objid, @rgcol, @commongen
  23764.         if @@ERROR <>0 or @retcode <> 0
  23765.                 return (1)
  23766.  
  23767.         /* Move on to next article, repeat while loop */
  23768.         select @artnick = min(nickname) from #nicknames_to_process where nickname > @artnick 
  23769.     end
  23770.  
  23771.     if (@articlesoption <> 1 and @articlesoption <> 3 and @articlesoption <> 4)
  23772.     begin
  23773.         /* Optimization: If joinchangegen and partchange are both null or < common gen,
  23774.         ** it is not necessary to expand #belong for that particular row.
  23775.         */
  23776.         
  23777.         select @maxfilterid = max(join_filterid) from sysmergesubsetfilters
  23778.  
  23779.         if @maxfilterid is not null
  23780.         begin
  23781.             update #belong set flag = @maxfilterid, skipexpand = 1 where isnull(joinchangegen,0) <= @commongen and
  23782.                 isnull(partchangegen,0) <= @commongen 
  23783.  
  23784.             /* Expand the #belong temptable */
  23785.             exec @retcode = dbo.sp_MSexpandbelongs @pubid
  23786.  
  23787.             if @@ERROR<>0 OR @retcode<>0
  23788.                 begin
  23789.                 return (1)
  23790.                 end
  23791.         end
  23792.     end
  23793.  
  23794.     /* If subscriber is sql server, we don't have to expand belongs */
  23795.     if (@articlesoption <> 1 and @articlesoption <> 3 and @articlesoption <> 4) and (@subissql = 0 or @dynamic_join_cnt > 0)
  23796.     begin
  23797.         /* Expand the #notbelong temptable */
  23798.         exec dbo.sp_MSexpandnotbelongs @pubid
  23799.         if @@error<>0 return(1)
  23800.     end
  23801.  
  23802. EXITPROC:
  23803.         
  23804.     /* transfer rows from local temp to global temp */
  23805.  
  23806.     -- Could have used if not exists instead of the following but want to use the KEEP PLAN option which is not supported in the IF EXISTS 
  23807.     select @belongsempty = 0
  23808.     select @belongsempty = 1 where not exists (select * from #belong) OPTION(KEEP PLAN)
  23809.     
  23810.     select @notbelongsempty = 0
  23811.     select @notbelongsempty = 1 where not exists (select * from #notbelong) OPTION(KEEP PLAN)
  23812.  
  23813.     /* If there are no rows in #belong, then drop the global ##belongs so that we do not call sp_MSenumpartialchanges */
  23814.     if (@belongsempty = 1)
  23815.     begin
  23816.         /* Post SQL 8.0 Beta 2 agents pass this flag with value 1 since they can handle NULL belongs table name */
  23817.         if @handle_null_tables = 1
  23818.             begin
  23819.                 exec ('drop table ' + @belongsname)
  23820.                 select @belongsname = NULL
  23821.             end
  23822.     end
  23823.     else
  23824.     begin
  23825.         exec ('insert into ' + @belongsname + ' (tablenick, rowguid, generation, lineage, colv) 
  23826.                 select distinct b.tablenick, b.rowguid, c.generation, c.lineage, c.colv1 from
  23827.                 #belong b left outer join dbo.MSmerge_contents c  
  23828.                 on  c.tablenick = b.tablenick and c.rowguid = b.rowguid ')
  23829.  
  23830.         if @@ERROR <>0    
  23831.         begin
  23832.                     return (1)
  23833.         end
  23834.  
  23835.         -- this index will be useful in sp_MSenumpartialchanges
  23836.         exec ('create index nc1belongstable on ' + @belongsname + ' (tablenick, rowguid) with FILLFACTOR = 100')
  23837.         if @@ERROR <>0    
  23838.             return (1)
  23839.     end
  23840.             
  23841.     /* If there are no rows in #notbelong, then drop the global ##notbelongs so that we do not call sp_MSenumpartialchanges */
  23842.     if (@notbelongsempty = 1)
  23843.     begin
  23844.         /* Post SQL 8.0 Beta 2 agents pass this flag with value 1 since they can handle NULL notbelongs table name */
  23845.         if @handle_null_tables = 1
  23846.             begin
  23847.                 exec ('drop table ' + @notbelongsname)
  23848.                 select @notbelongsname = NULL
  23849.             end
  23850.     end
  23851.     else
  23852.     begin
  23853.         /* transfer rows from local temp to global temp */
  23854.         exec ('insert into ' + @notbelongsname + ' (tablenick, rowguid, generation, lineage, type) 
  23855.                 select distinct b.tablenick, b.rowguid, coalesce (c.generation, t.generation), coalesce(c.lineage, t.lineage), b.type from
  23856.                 #notbelong b left outer join dbo.MSmerge_contents c  
  23857.                  on  c.tablenick = b.tablenick and c.rowguid = b.rowguid
  23858.                 left outer join dbo.MSmerge_tombstone t on t.tablenick = b.tablenick and t.rowguid = b.rowguid order by b.tablenick DESC, b.rowguid ASC ')
  23859.         if @@ERROR <>0    
  23860.         begin
  23861.             return (1)
  23862.         end
  23863.  
  23864.         -- this index will be useful in sp_MSenumpartialdeletes
  23865.         exec ('create index nc1notbelongstable on ' + @notbelongsname + ' (tablenick DESC, rowguid) with FILLFACTOR = 100')
  23866.         if @@ERROR <>0    
  23867.             return (1)
  23868.         
  23869.  
  23870.     end
  23871.     
  23872.     if (@belongsempty = 1)
  23873.         select @belongsname, @notbelongsname, -1
  23874.     else
  23875.     begin
  23876.         if (@articlesoption = 1)
  23877.         begin
  23878.             select @belongsname, @notbelongsname, @tablenickname
  23879.         end
  23880.         else
  23881.         begin
  23882.             select distinct @belongsname, @notbelongsname, tablenick from #belong 
  23883.         end
  23884.     end
  23885.  
  23886.     drop table #notbelong
  23887.     drop table #belong
  23888.     drop table #contents_subset
  23889.     drop table #tombstone_subset
  23890.     drop table #temp_cont 
  23891.     drop table #nicknames_to_process
  23892.     
  23893.     return (0)
  23894. go
  23895.  
  23896. exec dbo.sp_MS_marksystemobject sp_MSsetupbelongs
  23897. go
  23898. grant exec on dbo.sp_MSsetupbelongs to public
  23899. go
  23900.  
  23901. raiserror('Creating procedure sp_MSaddinitialarticle', 0,1)
  23902. GO
  23903.  
  23904. -- Called at the subscriber
  23905. CREATE PROCEDURE sp_MSaddinitialarticle(
  23906.     @article                sysname,         /* Name of the article */
  23907.     @artid                     uniqueidentifier,            /* Article ID */
  23908.     @pubid                     uniqueidentifier,            /* Publication ID */
  23909.     @nickname                int,                /* Article nickname */
  23910.     @column_tracking        int,                /* Does the article have column tracking ? */
  23911.     @status                    int,                /* Status of the article */
  23912.     @pre_creation_command    int = 0,             /* Precreate command of the article */
  23913.     @resolver_clsid            nvarchar(255) = NULL,/* Resolver module for the article */
  23914.     @insert_proc            nvarchar(255) = NULL,/* Insert sp for article */
  23915.     @update_proc            nvarchar(255) = NULL,/* Update sp for article */
  23916.     @select_proc            nvarchar(255) = NULL, /* Select SP for this article */
  23917.     @destination_object        sysname,            /* Destination object name */
  23918.     @missing_count            int             = NULL,    
  23919.     @missing_cols            varbinary(32) = NULL,
  23920.     @article_resolver        nvarchar(255) = NULL,
  23921.     @resolver_info            nvarchar(255) = NULL,
  23922.     @filter_clause            nvarchar(2000) = NULL,
  23923.     @excluded_count            int             = NULL,
  23924.     @excluded_cols            varbinary(32)    = NULL,
  23925.     @destination_owner        sysname         = NULL,
  23926.     @identity_support        int                = 0,
  23927.     @verify_resolver_signature int            = 0,                            /* 0=do not verify signature, 1=verify that signature is from trusted source, more values may be added later */
  23928.     @fast_multicol_updateproc bit            = 0
  23929.     ) AS
  23930.     
  23931.     SET NOCOUNT ON
  23932.  
  23933.     declare @objid int
  23934.     declare @sub_missing_cols binary(32)
  23935.     declare @retcode int
  23936.     /*
  23937.     ** Check for subscribing permission
  23938.     */
  23939.     exec @retcode=sp_MSreplcheck_subscribe
  23940.     if @retcode<>0 or @@ERROR<>0 return (1)
  23941.     
  23942.     if (@artid is NULL)
  23943.         BEGIN
  23944.             RAISERROR (14057, 16, -1)
  23945.             RETURN (1)
  23946.         END
  23947.  
  23948.     /*
  23949.     ** The columns that do not belong to the partition at subscriber side are nothing but
  23950.     ** missing columns to the subscriber side - it just does not have them !
  23951.     ** For the same reason, the excluded ones from publisher does not mean anything to
  23952.     ** subscriber, which does not exclude anything for itself. We just reset to 0
  23953.     */
  23954.     select @missing_count = @missing_count + @excluded_count
  23955.     exec @retcode= master..xp_ORbitmap @missing_cols, @excluded_cols, @sub_missing_cols OUTPUT
  23956.     if @@error<>0 or @retcode<>0 return(1)
  23957.     
  23958.     if (@resolver_clsid='') select @resolver_clsid = NULL
  23959.     if (@filter_clause='') set @filter_clause = NULL
  23960.     
  23961.     /*
  23962.     ** Populate the local copy of sysmergearticles
  23963.     */
  23964.     if exists (select * from sysmergearticles where artid = @artid and pubid = @pubid )
  23965.         begin
  23966.             update sysmergearticles 
  23967.                 set name = @article,
  23968.                     artid = @artid,
  23969.                     pre_creation_command = pre_creation_command,
  23970.                     pubid = @pubid,
  23971.                     nickname = @nickname,
  23972.                     column_tracking = @column_tracking,
  23973.                     status    = @status,
  23974.                     resolver_clsid = @resolver_clsid,
  23975.                     insert_proc = @insert_proc,
  23976.                     update_proc =  @update_proc,
  23977.                     select_proc = @select_proc,
  23978.                     destination_object = @destination_object,
  23979.                     destination_owner = @destination_owner,
  23980.                     missing_col_count = @missing_count,
  23981.                     missing_cols = @sub_missing_cols,
  23982.                     article_resolver = @article_resolver,
  23983.                     resolver_info = @resolver_info,
  23984.                     subset_filterclause = @filter_clause,
  23985.                     excluded_col_count = 0,
  23986.                     excluded_cols = 0x00,
  23987.                     identity_support=@identity_support,
  23988.                     verify_resolver_signature = @verify_resolver_signature,
  23989.                     fast_multicol_updateproc = @fast_multicol_updateproc
  23990.                 where artid = @artid and pubid = @pubid
  23991.         end
  23992.     else
  23993.         begin
  23994.             select @objid = 0
  23995.             insert sysmergearticles (name, type, objid, sync_objid, artid, pre_creation_command, pubid, 
  23996.                 nickname, column_tracking, status, resolver_clsid, destination_owner,
  23997.                 insert_proc, update_proc, select_proc, destination_object, missing_col_count, missing_cols, 
  23998.                 article_resolver, resolver_info, subset_filterclause, excluded_col_count, excluded_cols, identity_support,
  23999.                 verify_resolver_signature, fast_multicol_updateproc)
  24000.             values (@article, 0x0a, @objid, @objid, @artid, @pre_creation_command, @pubid, 
  24001.                 @nickname, @column_tracking, @status, @resolver_clsid, @destination_owner,
  24002.                 @insert_proc, @update_proc, @select_proc, @destination_object, @missing_count, @sub_missing_cols, 
  24003.                 @article_resolver, @resolver_info, @filter_clause, 0, 0x00, @identity_support, @verify_resolver_signature, @fast_multicol_updateproc)
  24004.         end
  24005.     IF @@ERROR <> 0
  24006.         BEGIN
  24007.         RAISERROR (14057, 16, -1)
  24008.         RETURN (1)
  24009.     END
  24010.  
  24011.  
  24012.     RETURN 0
  24013. go
  24014.  
  24015. exec dbo.sp_MS_marksystemobject sp_MSaddinitialarticle
  24016. go
  24017. grant exec on dbo.sp_MSaddinitialarticle to public
  24018. go
  24019.  
  24020. raiserror('Creating procedure sp_MSaddinitialschemaarticle', 0,-1)
  24021. go
  24022. CREATE PROCEDURE sp_MSaddinitialschemaarticle(
  24023.     @name                 sysname,
  24024.     @destination_object   sysname,
  24025.     @destination_owner    sysname,
  24026.     @artid                uniqueidentifier,
  24027.     @pubid                uniqueidentifier,
  24028.     @pre_creation_command tinyint,
  24029.     @status               int,
  24030.     @type                 tinyint
  24031. )as    
  24032. begin
  24033.     set nocount on
  24034.     
  24035.     declare @objid int
  24036.     declare @old_objid int
  24037.     declare @retcode int
  24038.     declare @qualified_name nvarchar(270)
  24039.  
  24040.     /*
  24041.     ** Security check
  24042.     */
  24043.     exec @retcode=sp_MSreplcheck_subscribe
  24044.     if @retcode<>0 or @@ERROR<>0 return(1)
  24045.     
  24046.     if (@artid is NULL)
  24047.     begin
  24048.         raiserror (14057, 16, -1)
  24049.         return 1
  24050.     end
  24051.  
  24052.     if @destination_owner is null or @destination_owner = ''
  24053.     begin
  24054.         select @destination_owner = user_name()
  24055.     end
  24056.  
  24057.     select @qualified_name = quotename(@destination_owner) + '.' + quotename(@destination_object)
  24058.  
  24059.     select @objid = object_id(@qualified_name)
  24060.  
  24061.     select @old_objid = null
  24062.     select @old_objid = objid from sysmergeschemaarticles 
  24063.      where artid = @artid
  24064.        and pubid = @pubid
  24065.  
  24066.     -- Update the objid field of all merge schema articles with the same article id
  24067.     update sysmergeschemaarticles 
  24068.         set objid = @objid 
  24069.             where artid = @artid
  24070.  
  24071.     -- Update the objid field of all transactional schema articles with the same article id or same old objid
  24072.     if @old_objid is not null and @objid <> @old_objid
  24073.     begin
  24074.         if exists (select * from sysobjects where name = 'sysschemaarticles')
  24075.         begin
  24076.             update sysschemaarticles 
  24077.                set objid = @objid 
  24078.              where objid = @old_objid
  24079.         end  
  24080.     end
  24081.  
  24082.     begin transaction
  24083.  
  24084.     if exists (select * from sysmergeschemaarticles where artid = @artid and pubid = @pubid)
  24085.     begin
  24086.         
  24087.  
  24088.         update dbo.sysmergeschemaarticles
  24089.            set name = @name,
  24090.                destination_object = @destination_object,
  24091.                destination_owner = @destination_owner,
  24092.                pre_creation_command = @pre_creation_command,
  24093.                status = @status,
  24094.                type = @type
  24095.          where artid = @artid
  24096.            and pubid = @pubid              
  24097.  
  24098.         if @@error<>0
  24099.         begin
  24100.             rollback transaction
  24101.             return 1
  24102.         end
  24103.  
  24104.     end
  24105.     else
  24106.     begin
  24107.  
  24108.         insert dbo.sysmergeschemaarticles
  24109.             (name, type, objid, artid, description, pre_creation_command, 
  24110.              pubid, status, creation_script, schema_option, destination_object,
  24111.              destination_owner)
  24112.         values 
  24113.             (@name, @type, @objid, @artid, NULL, @pre_creation_command,
  24114.              @pubid, @status, NULL, 0x0000000000000000, @destination_object,
  24115.              @destination_owner)
  24116.         if @@error<>0
  24117.         begin
  24118.             rollback transaction
  24119.             return 1
  24120.         end
  24121.         
  24122.     end
  24123.  
  24124.     exec @retcode = dbo.sp_MSmarkschemaobject @destination_object, @destination_owner
  24125.     if @@error<>0 or @retcode<>0
  24126.     begin
  24127.         rollback transaction
  24128.         return 1    
  24129.     end 
  24130.     commit transaction
  24131.  
  24132.     return 0
  24133. end
  24134. go
  24135. exec dbo.sp_MS_marksystemobject sp_MSaddinitialschemaarticle
  24136. go
  24137. grant exec on dbo.sp_MSaddinitialschemaarticle to public
  24138. go
  24139.  
  24140.  
  24141. raiserror('Creating procedure sp_MSaddinitialpublication', 0,1)
  24142. GO
  24143.  
  24144. CREATE PROCEDURE sp_MSaddinitialpublication(
  24145.     @publisher                sysname,
  24146.     @publisher_db             sysname,
  24147.     @publication            sysname,             /* Name of the publication */
  24148.     @description            nvarchar(255),         /* Description of the publication */
  24149.     @pubid                     uniqueidentifier,    /* Publication ID */
  24150.     @retention                int,                /* Retention period of the publication */
  24151.     @sync_mode                int,                /* Sync mode of the publication */
  24152.     @allow_push                int,                /* does publication allow push ? */
  24153.     @allow_pull                int,                /* does publication allow pull ? */
  24154.     @allow_anonymous        int,                /* does publication allow anonymous ? */
  24155.     @centralized_conflicts    int,                 /* publication does centralized conflicts ? */
  24156.     @status                    int,                 /* publication's status */
  24157.     @snapshot_ready            int,                 /* publication snapshto_ready flag ? */
  24158.     @enabled_for_internet    int,                 /* publication enabled_for_internet flag ? */
  24159.     @publication_type        int,                /* a full publication or a partial one */
  24160.     @conflict_retention        int = 60,                /* the retention period for conflict table */
  24161.     @allow_subscription_copy int = 0,                /* does publication allow subscription copies to sync ? */
  24162.     @allow_synctoalternate     int = 0,                /* does publication allow subscription to sync to alternates ? */
  24163.     @backward_comp_level    int = 10            /* default to 7.0 server */
  24164.     ) AS
  24165.     
  24166.     SET NOCOUNT ON
  24167.     declare @retcode             int
  24168.     declare @publisher_srvid     int
  24169.  
  24170.     select @publication = RTRIM(@publication)
  24171.     select @publisher_db = RTRIM(@publisher_db)
  24172.  
  24173.     /*
  24174.     ** Check for subscribing permission
  24175.     */
  24176.     exec @retcode=sp_MSreplcheck_subscribe
  24177.     if @retcode<>0 or @@ERROR<>0 return (1)
  24178.  
  24179.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  24180.     if @publisher_srvid is NULL
  24181.         begin
  24182.         EXECUTE @retcode = dbo.sp_addserver @publisher, @duplicate_ok='duplicate_ok'
  24183.  
  24184.         IF @@error <> 0 OR @retcode <> 0
  24185.             BEGIN
  24186.                 RAISERROR (14042, 16, -1)
  24187.                 RETURN (1)
  24188.             END
  24189.         end                
  24190.  
  24191.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  24192.     IF @publisher_srvid IS NULL
  24193.         BEGIN
  24194.             RAISERROR (14010, 16, -1)
  24195.             RETURN (1)
  24196.         END
  24197.     
  24198.     /*
  24199.     ** Populate the local copy of sysmergepublications
  24200.     */
  24201.     BEGIN TRAN
  24202.     save TRAN MSaddinitialpublication
  24203.     
  24204.     if exists (select * from sysmergepublications 
  24205.             where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db)
  24206.         begin 
  24207.             declare @pubid_local uniqueidentifier
  24208.  
  24209.             /* select the local pubid only if it has a valid parentid */
  24210.             select @pubid_local = pubid    from sysmergepublications 
  24211.                 where name = @publication and 
  24212.                     UPPER(publisher)=UPPER(@publisher) and 
  24213.                     publisher_db=@publisher_db
  24214.             if exists (select * from sysmergesubscriptions 
  24215.                 where pubid = @pubid and srvid = @publisher_srvid and db_name = @publisher_db)
  24216.                     begin
  24217.                         delete from sysmergesubscriptions 
  24218.                             where pubid = @pubid and srvid = @publisher_srvid and db_name = @publisher_db
  24219.                         IF @@ERROR <> 0
  24220.                             BEGIN
  24221.                                 RAISERROR (14057, 16, -1)
  24222.                                 goto FAILURE
  24223.                             END
  24224.                     end
  24225.             update sysmergesubscriptions SET pubid = @pubid where pubid = @pubid_local
  24226.             IF @@ERROR <> 0
  24227.                 BEGIN
  24228.                     RAISERROR (14057, 16, -1)
  24229.                     goto FAILURE
  24230.                 END
  24231.             if @pubid <> @pubid_local
  24232.                 delete from sysmergesubscriptions where subid = @pubid
  24233.                 
  24234.             update sysmergesubscriptions SET subid = @pubid where subid = @pubid_local
  24235.             IF @@ERROR <> 0
  24236.                 BEGIN
  24237.                     RAISERROR (14057, 16, -1)
  24238.                     goto FAILURE
  24239.                 END
  24240.             update sysmergesubscriptions    
  24241.                 SET partnerid = @pubid
  24242.                 where partnerid = @pubid_local
  24243.         
  24244.             IF @@ERROR <> 0
  24245.                 BEGIN
  24246.                     RAISERROR (14057, 16, -1)
  24247.                     goto FAILURE
  24248.                 END
  24249.             update sysmergepublications 
  24250.                 SET pubid = @pubid, 
  24251.                     name = @publication, 
  24252.                     description = @description, 
  24253.                     designmasterid = @pubid, 
  24254.                     retention = @retention, 
  24255.                     parentid = pubid, 
  24256.                     sync_mode = sync_mode, 
  24257.                     allow_push = @allow_push, 
  24258.                     allow_pull = @allow_pull, 
  24259.                     allow_anonymous = @allow_anonymous, 
  24260.                     centralized_conflicts = @centralized_conflicts,
  24261.                     status = @status,
  24262.                     snapshot_ready = @snapshot_ready,
  24263.                     enabled_for_internet = @enabled_for_internet,
  24264.                     publication_type = @publication_type,
  24265.                     conflict_retention = @conflict_retention,
  24266.                     allow_subscription_copy = @allow_subscription_copy, 
  24267.                     allow_synctoalternate = @allow_synctoalternate ,
  24268.                     backward_comp_level = @backward_comp_level
  24269.                 where name = @publication
  24270.                       and UPPER(publisher) = UPPER(@publisher)
  24271.                       and publisher_db = @publisher_db
  24272.         end
  24273.     else
  24274.         begin
  24275.             insert sysmergepublications(publisher, publisher_db,pubid, name, description, designmasterid, 
  24276.                 retention, parentid, sync_mode, allow_push, allow_pull, allow_anonymous, 
  24277.                 centralized_conflicts, status, snapshot_ready, enabled_for_internet, publication_type, 
  24278.                 conflict_retention, allow_subscription_copy, allow_synctoalternate, backward_comp_level)
  24279.             values(@publisher, @publisher_db, @pubid, @publication, @description, @pubid, 
  24280.                 @retention, @pubid, @sync_mode, @allow_push, @allow_pull, @allow_anonymous, 
  24281.                 @centralized_conflicts, @status, @snapshot_ready, @enabled_for_internet, @publication_type, 
  24282.                 @conflict_retention, @allow_subscription_copy, @allow_synctoalternate, @backward_comp_level)
  24283.         end
  24284.     IF @@ERROR <> 0
  24285.         BEGIN
  24286.             RAISERROR (14057, 16, -1)
  24287.             goto FAILURE
  24288.         END
  24289.     COMMIT TRAN
  24290.  
  24291.     RETURN (0)
  24292.  
  24293. FAILURE:
  24294.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  24295.     if @@TRANCOUNT > 0
  24296.     begin
  24297.         ROLLBACK TRANSACTION MSaddinitialpublication
  24298.         COMMIT TRANSACTION
  24299.     end
  24300.     RETURN (1)
  24301. go
  24302. exec dbo.sp_MS_marksystemobject sp_MSaddinitialpublication
  24303. go
  24304. grant exec on dbo.sp_MSaddinitialpublication to public
  24305. go
  24306.  
  24307. raiserror('Creating procedure sp_MSaddinitialsubscription', 0,1)
  24308. GO
  24309.  
  24310. CREATE PROCEDURE sp_MSaddinitialsubscription(
  24311.     @pubid                     uniqueidentifier,        /* Publication ID */
  24312.     @subid                     uniqueidentifier,          /* Subscription's replica ID */
  24313.     @partnerid                 uniqueidentifier,          /* Partner's replica ID */
  24314.     @subscriber                sysname,                 /* Subscriber server */
  24315.     @subscriber_db            sysname,                  /* Subscriber database */
  24316.     @subscriber_priority     real = 0.0,                 /* Subscriber priority */
  24317.     @subscriber_type        tinyint = 0,            /* Subscriber type - local, global, or anonymous */
  24318.     @subscription_type         int = 0,                /* Subscription type - push or pull */
  24319.     @sync_type                 tinyint = 2,            /* Subscription sync type 1 = no sync, 2 = automatic */
  24320.     @publication            sysname = NULL,            /* Publication Name */
  24321.     @distributor            sysname = NULL            /* Distributor */
  24322.     ) AS
  24323.     
  24324.     SET NOCOUNT ON
  24325.  
  24326.     /*
  24327.     ** Declarations.
  24328.     */
  24329.     DECLARE @local                 tinyint
  24330.     DECLARE @anonymous             tinyint
  24331.     DECLARE @subscriber_srvid    int
  24332.     DECLARE @subnickname        int
  24333.     DECLARE @active             tinyint
  24334.     DECLARE @retcode            int
  24335.     DECLARE    @subid_old            uniqueidentifier
  24336.  
  24337.     
  24338.     /* 
  24339.     ** Initializations
  24340.     */
  24341.     SET @local                 = 2
  24342.     SET @anonymous             = 3
  24343.     set @active             = 1 /* after this SP is called, the subscription is activated */
  24344.  
  24345.     select @subscriber_db = RTRIM(@subscriber_db)
  24346.     /*
  24347.     ** Check for subscribing permission
  24348.     ** It is called by merge agent at the publisher side
  24349.     ** subscriber side?
  24350.     */
  24351.     -- @pubid is not local
  24352.     if sessionproperty('replication_agent') = 0
  24353.     begin
  24354.         exec @retcode= dbo.sp_MSreplcheck_connection
  24355.             @pubid = @pubid
  24356.         if @retcode<>0 or @@ERROR<>0 return (1)
  24357.     end
  24358.  
  24359.     -- this gets executed at both publisher (for pull subscriptions) and at subscriber
  24360.     --  if server is not found use srvid of 0 for local srvid
  24361.     
  24362.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  24363.     if @subscriber_srvid is null
  24364.         set @subscriber_srvid = 0
  24365.  
  24366.     begin tran
  24367.     save TRAN MSaddinitialsubscription    
  24368.         /*
  24369.         ** Populate the local copy of sysmergesubscriptions
  24370.         */
  24371.     if exists (select * from sysmergesubscriptions where subid = @subid)
  24372.             begin
  24373.                 update sysmergesubscriptions 
  24374.                     SET    subid = @subid,
  24375.                         datasource_type = 0,
  24376.                         datasource_path = NULL,
  24377.                         srvid = @subscriber_srvid,
  24378.                         db_name = @subscriber_db,
  24379.                         pubid = @pubid,
  24380.                         status = @active,
  24381.                         subscriber_type = @subscriber_type,
  24382.                         subscription_type =    @subscription_type,
  24383.                         priority = @subscriber_priority,
  24384.                         sync_type = @sync_type,
  24385.                         subscriber_server = @subscriber,
  24386.                         publication = @publication,
  24387.                         distributor = @distributor
  24388.                     where subid = @subid 
  24389.                             
  24390.                 IF @@ERROR <> 0
  24391.                     BEGIN
  24392.                         goto FAILURE
  24393.                     END
  24394.             end                    
  24395.                     
  24396.         if exists (select * from sysmergesubscriptions where srvid = @subscriber_srvid AND db_name = @subscriber_db AND pubid = @pubid)
  24397.             begin
  24398.                 select @subid_old = subid from sysmergesubscriptions where srvid = @subscriber_srvid AND db_name = @subscriber_db AND pubid = @pubid
  24399.                 update sysmergesubscriptions 
  24400.                     SET    subid = @subid,
  24401.                         datasource_type = 0,
  24402.                         datasource_path = NULL,
  24403.                         srvid = @subscriber_srvid,
  24404.                         db_name = @subscriber_db,
  24405.                         pubid = @pubid,
  24406.                         status = @active,
  24407.                         subscriber_type = @subscriber_type,
  24408.                         subscription_type =    @subscription_type,
  24409.                         priority = @subscriber_priority,
  24410.                         sync_type = @sync_type,
  24411.                         subscriber_server = @subscriber,
  24412.                         publication = @publication,
  24413.                         distributor = @distributor
  24414.                     where srvid = @subscriber_srvid AND db_name = @subscriber_db  AND pubid = @pubid
  24415.                             
  24416.                 IF @@ERROR <> 0
  24417.                     BEGIN
  24418.                         goto FAILURE
  24419.                     END
  24420.                 if (@subid_old IS NOT NULL)
  24421.                     begin
  24422.                         /*
  24423.                         **  Delete old row for subscriber from MSmerge_replinfo.
  24424.                         */
  24425.                         DELETE from MSmerge_replinfo where repid = @subid_old
  24426.                         IF @@ERROR <> 0
  24427.                             BEGIN
  24428.                                 goto FAILURE
  24429.                             END
  24430.  
  24431.                         EXECUTE @retcode = dbo.sp_MSgenreplnickname @subid, @subnickname output
  24432.                         if @@ERROR<>0 or @retcode<>0 goto FAILURE
  24433.                         
  24434.                         /*
  24435.                         **  Add new row for subscriber to MSmerge_replinfo.
  24436.                         */
  24437.                         INSERT INTO  MSmerge_replinfo(repid, replnickname)    
  24438.                             values (@subid, @subnickname) 
  24439.                         IF @@ERROR <> 0
  24440.                             BEGIN
  24441.                                 goto FAILURE
  24442.                             END
  24443.                     end                    
  24444.             end
  24445.         else
  24446.             begin
  24447.                 INSERT sysmergesubscriptions(subid,
  24448.                                           partnerid,
  24449.                                           datasource_type, 
  24450.                                           datasource_path, 
  24451.                                           srvid, 
  24452.                                           db_name, 
  24453.                                           pubid,
  24454.                                           status, 
  24455.                                           subscriber_type,
  24456.                                           subscription_type,
  24457.                                           priority, 
  24458.                                           sync_type, 
  24459.                                           description,
  24460.                                           login_name,
  24461.                                           subscriber_server,
  24462.                                           publication,
  24463.                                           distributor)
  24464.                     VALUES (@subid,
  24465.                             @partnerid,
  24466.                             0,
  24467.                             NULL,
  24468.                                @subscriber_srvid,
  24469.                               @subscriber_db,
  24470.                                @pubid,
  24471.                             @active,
  24472.                             @subscriber_type,
  24473.                             @subscription_type,
  24474.                             @subscriber_priority,
  24475.                             @sync_type, 
  24476.                             NULL, 
  24477.                             suser_sname(suser_sid()),
  24478.                             @subscriber,
  24479.                             @publication,
  24480.                             @distributor)
  24481.  
  24482.                 IF @@ERROR <> 0
  24483.                     BEGIN
  24484.                         goto FAILURE
  24485.                     END
  24486.  
  24487.                 /* Look for existing nickname from any other subscription */
  24488.                 select @subnickname = max(replnickname) from MSmerge_replinfo,
  24489.                      sysmergesubscriptions where repid = subid 
  24490.                          and srvid = @subscriber_srvid 
  24491.                          and    db_name = @subscriber_db
  24492.                 /* Generate a new replica nickname from the @subid */
  24493.                 if (@subnickname is null)
  24494.                     begin
  24495.                         EXECUTE @retcode = dbo.sp_MSgenreplnickname @subid, @subnickname output
  24496.                         if @@ERROR<>0 or @retcode<>0 goto FAILURE
  24497.                     end
  24498.                 /*
  24499.                 **  Add row for subscriber to MSmerge_replinfo.
  24500.                 */
  24501.                 INSERT INTO  MSmerge_replinfo(repid, replnickname)    
  24502.                     values (@subid, @subnickname) 
  24503.                 IF @@ERROR <> 0
  24504.                     BEGIN
  24505.                         goto FAILURE
  24506.                     END
  24507.             end                                        
  24508.  
  24509.  
  24510.     COMMIT TRAN            
  24511.     RETURN 0
  24512.  
  24513. FAILURE:
  24514.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  24515.     if @@TRANCOUNT > 0
  24516.     begin
  24517.         ROLLBACK TRANSACTION MSaddinitialsubscription
  24518.         COMMIT TRANSACTION
  24519.     end
  24520.     
  24521.     RAISERROR (14057, 16, -1)
  24522.     RETURN 1
  24523. go
  24524. exec dbo.sp_MS_marksystemobject sp_MSaddinitialsubscription
  24525. go
  24526. grant exec on dbo.sp_MSaddinitialsubscription to public
  24527. go 
  24528.  
  24529. raiserror('Creating procedure sp_MSmakearticleprocs', 0,1)
  24530. GO
  24531.  
  24532. create procedure sp_MSmakearticleprocs
  24533.     (@pubid uniqueidentifier, @artid uniqueidentifier)
  24534. as
  24535.     declare @ownername sysname
  24536.     declare @objectname sysname
  24537.     declare @ins_procname sysname
  24538.     declare @sel_procname sysname
  24539.     declare @upd_procname sysname
  24540.     declare @guidstr nvarchar(40)
  24541.     declare @trigname         sysname
  24542.     declare @objid int
  24543.     declare @dbname            sysname
  24544.     declare @command        nvarchar(1000)
  24545.     
  24546.     -- to be called after article is set up in a subscriber
  24547.     declare @retcode smallint
  24548.  
  24549.     /*
  24550.     ** Check for subscribing permission
  24551.     */
  24552.     exec @retcode=sp_MSreplcheck_subscribe
  24553.     if @retcode<>0 or @@ERROR<>0 return (1)
  24554.  
  24555.     select @objid = max(objid) from sysmergearticles where artid = @artid
  24556.     -- get owner name, and table name
  24557.     select @objectname = name, @ownername = user_name(uid)
  24558.         from sysobjects    where id = @objid
  24559.  
  24560.     -- get the  insert and update proc names from sys articles
  24561.     select @ins_procname = insert_proc, @upd_procname = update_proc, @sel_procname = select_proc
  24562.         from sysmergearticles where pubid = @pubid and artid = @artid
  24563.  
  24564.     if object_id(@ins_procname) is not NULL
  24565.     begin
  24566.         exec ('drop proc ' + @ins_procname)
  24567.         if @@ERROR<>0 
  24568.             return (1)
  24569.     end
  24570.  
  24571.     if object_id(@upd_procname) is not NULL
  24572.     begin
  24573.         exec ('drop proc ' + @upd_procname)
  24574.         if @@ERROR<>0
  24575.             return (1)
  24576.     end
  24577.  
  24578.     if object_id(@sel_procname) is not NULL
  24579.     begin
  24580.         exec ('drop proc ' + @sel_procname)
  24581.         if @@ERROR<>0
  24582.             return (1)
  24583.     end
  24584.  
  24585.     -- create the procs
  24586.     set @dbname = db_name()
  24587.     /* If procedure already exists because article in multiple pubs don't bother */
  24588.     if not exists (select * from sysobjects where name = @ins_procname and type = 'P')
  24589.         begin
  24590.         set @command = 'sp_MSmakeinsertproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @ins_procname  + ', [' + convert(nchar(36), @pubid) + ']'
  24591.         exec @retcode = master..xp_execresultset @command, @dbname
  24592.         if @@ERROR<>0 OR @retcode <>0 return (1)
  24593.         exec @retcode = dbo.sp_MS_marksystemobject  @ins_procname 
  24594.         if @@ERROR<>0 OR @retcode <>0 return (1)
  24595.  
  24596.         exec ('grant exec on ' + @ins_procname + ' to public')
  24597.         if @@ERROR<>0 return (1)
  24598.         end
  24599.  
  24600.     /* If procedure already exists because article in multiple pubs don't bother */
  24601.     if not exists (select * from sysobjects where name = @upd_procname and type = 'P')
  24602.         begin
  24603.         set @command = 'sp_MSmakeupdateproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @upd_procname + ', [' + convert(nchar(36), @pubid) + ']'
  24604.         exec @retcode = master..xp_execresultset @command, @dbname
  24605.         if @@ERROR<>0 OR @retcode <>0 return (1)
  24606.         exec @retcode = dbo.sp_MS_marksystemobject  @upd_procname 
  24607.         if @@ERROR<>0 or @retcode <>0 return (1)
  24608.         exec ('grant exec on ' + @upd_procname + ' to public')
  24609.         if @@ERROR<>0 return (1)
  24610.         end
  24611.         
  24612.     /* If procedure already exists because article in multiple pubs don't bother */
  24613.     if not exists (select * from sysobjects where name = @sel_procname and type = 'P')
  24614.         begin
  24615.         set @command = 'sp_MSmakeselectproc ' + QUOTENAME(@objectname) + ' , ' + QUOTENAME(@ownername) + ' , ' + @sel_procname + ', [' + convert(nchar(36), @pubid) + ']'
  24616.         exec @retcode = master..xp_execresultset @command, @dbname
  24617.         if @@ERROR<>0 or @retcode<>0
  24618.             return (1)
  24619.         exec @retcode = dbo.sp_MS_marksystemobject  @sel_procname 
  24620.         if @@ERROR<>0 OR @retcode <>0 return (1)
  24621.  
  24622.         exec ('grant exec on ' + @sel_procname + ' to public')
  24623.         if @@ERROR<>0 return (1)
  24624.         end
  24625.         
  24626. go
  24627. exec dbo.sp_MS_marksystemobject sp_MSmakearticleprocs
  24628. go
  24629. grant exec on dbo.sp_MSmakearticleprocs to public
  24630. go
  24631.  
  24632. raiserror('Creating procedure sp_MSupdatesysmergearticles', 0,1)
  24633. GO
  24634.  
  24635. CREATE PROCEDURE sp_MSupdatesysmergearticles(
  24636.     @object                    sysname,                 /* Name of the table */
  24637.     @artid                    uniqueidentifier,        /* Article ID */
  24638.     @owner                    sysname             = NULL,
  24639.     @identity_support        int                    = NULL,
  24640.     @next_seed                bigint                = NULL,
  24641.     @range                    bigint                = NULL,
  24642.     @threshold                int                    = NULL,
  24643.     @pubid                    uniqueidentifier     = NULL
  24644.     ) AS
  24645.     declare @merge_pub_object_bit     int
  24646.     declare @id                        int
  24647.     declare @qualified_name            nvarchar(270)
  24648.     declare @colid                    int
  24649.     declare @colname                sysname
  24650.     declare @mergepublish            int
  24651.     SET NOCOUNT ON
  24652.     
  24653.     declare @retcode int
  24654.     declare @objid int
  24655.  
  24656.     if @owner is NULL or @owner = ''
  24657.     begin
  24658.         if exists (select name from sysobjects where id = object_id(@object))
  24659.             select @owner = user_name(uid) from sysobjects where id = object_id(QUOTENAME(@object))
  24660.         else 
  24661.             begin
  24662.                 raiserror(21078, 16, -1, @object)
  24663.                 return (1)
  24664.             end
  24665.     end
  24666.  
  24667.     select @mergepublish = 0x4000
  24668.     
  24669.     select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object)
  24670.     select @objid = object_id(@qualified_name)
  24671.     
  24672.     /*
  24673.     ** Check to see if current publication has permission
  24674.     */
  24675.     /*
  24676.     ** Check for subscribing permission
  24677.     */
  24678.     exec @retcode=sp_MSreplcheck_subscribe
  24679.     if @retcode<>0 or @@ERROR<>0 return (1)
  24680.     
  24681.     select @merge_pub_object_bit     = 128
  24682.  
  24683.     if (@artid is NULL)
  24684.     BEGIN
  24685.         RAISERROR (14057, 16, -1)
  24686.         RETURN (1)
  24687.     END
  24688.     begin tran
  24689.     save tran sp_MSupdatesysmergearticles
  24690.         if exists (select name from sysobjects where id = @objid)
  24691.         begin
  24692.             exec dbo.sp_replupdateschema @qualified_name
  24693.             if @@ERROR<>0 goto UNDO
  24694.             update sysobjects set replinfo = replinfo | @merge_pub_object_bit where id=@objid
  24695.             if @@ERROR<>0 goto UNDO
  24696.             update syscolumns set colstat=colstat | @mergepublish where id=@objid
  24697.             if @@ERROR<>0 goto UNDO
  24698.         /*
  24699.         ** update sysmergearticles.objid for all articles sharing the same base table
  24700.         */
  24701.         update sysmergearticles set objid = @objid where artid = @artid
  24702.             IF @@ERROR <> 0
  24703.             BEGIN
  24704.             RAISERROR (14057, 16, -1)
  24705.             goto UNDO
  24706.         END
  24707.         /*
  24708.         ** update sysmergearticles.sysnc_objid for only the article in this publication
  24709.         ** and for articles that no longer has a valid sync_objid (usually for the
  24710.         ** non-filtered case)
  24711.         */
  24712.         update sysmergearticles set sync_objid=@objid 
  24713.          where artid = @artid 
  24714.            and (pubid = @pubid or 
  24715.                 (object_name(sync_objid) is null and isnull(view_type,0) = 0))
  24716.         IF @@ERROR <> 0
  24717.         BEGIN
  24718.             RAISERROR (14057, 16, -1)
  24719.             goto UNDO
  24720.         END
  24721.             
  24722.             
  24723.         /*
  24724.         ** Set the next_seed, max value, and threshhold of identity table. New range and threshold are to be set
  24725.         ** by sp_addmergearticle if the table is to be republished. Message based subscribers have to look up the
  24726.         ** threshold and range info to see if they need to request a new range. Use max_identity for current_max for
  24727.         ** now. The value of current_max can change by sp_addmergearticle if republished.
  24728.         */
  24729.         if @identity_support = 1
  24730.         begin
  24731.             exec @retcode = sp_MSreseed @objid, @next_seed, @range
  24732.             if @@ERROR<>0 or @retcode<>0
  24733.                 GOTO UNDO
  24734.             insert MSrepl_identity_range (objid, max_identity, next_seed, current_max, range, threshold) 
  24735.                 values(@objid, @next_seed + @range, @next_seed, @next_seed + @range - 1, @range, @threshold)
  24736.             if @@ERROR<>0
  24737.             begin
  24738.                 GOTO UNDO
  24739.             end
  24740.         end
  24741.         
  24742.         end
  24743.         else -- THIS IS FINE. This dynamic query is there to provide a good error message. No need to use SP.
  24744.             raiserror(21078, 16, -1, @object)
  24745.             exec dbo.sp_replupdateschema @qualified_name
  24746.             if @@error<>0 goto UNDO
  24747.     commit tran
  24748.     RETURN 0
  24749. UNDO:
  24750.     rollback tran sp_MSupdatesysmergearticles
  24751.     commit tran
  24752.     RETURN 1
  24753. go
  24754. exec dbo.sp_MS_marksystemobject sp_MSupdatesysmergearticles
  24755. go
  24756. grant exec on dbo.sp_MSupdatesysmergearticles to public
  24757. go
  24758.  
  24759.  
  24760. raiserror('Creating procedure sp_MSexclause', 0,1)
  24761. GO
  24762.  
  24763. create proc sp_MSexclause  @tablenick int, @pubid uniqueidentifier  as
  24764. set nocount on
  24765. declare @clause nvarchar(4000)
  24766. declare @filterid int
  24767. declare @joinnick int
  24768. declare @jointable nvarchar(270)
  24769. declare @table nvarchar(270)
  24770. declare @basetable nvarchar(270)
  24771. declare @filter_clause nvarchar(2000)
  24772. declare @retcode int
  24773.  
  24774. exec @retcode= sp_MStablenamefromnick @tablenick, @basetable out
  24775. if @@error<>0 or @retcode<>0 return(1)
  24776. select @table = QUOTENAME(name)  from sysobjects where id in (select 
  24777.             objid from sysmergearticles where nickname = @tablenick)
  24778.  
  24779. declare f_c CURSOR LOCAL FAST_FORWARD for  select art_nickname, join_filterclause 
  24780.     from sysmergesubsetfilters where join_nickname = @tablenick and pubid = @pubid
  24781.     FOR READ ONLY
  24782. open f_c
  24783. fetch next from f_c into @joinnick, @filter_clause
  24784. while (@@fetch_status <> -1)
  24785.     begin
  24786.     exec @retcode= sp_MStablenamefromnick @joinnick, @jointable out
  24787.     if @@error<>0 or @retcode<>0 goto Failure
  24788.     -- As helper proc for sp_MSmakeinsertproc, we can insert directly to the
  24789.     -- temp table as we build up more commands for the insert proc.
  24790.     -- Our commands are part of phase 8...
  24791.     set @clause = ' 
  24792.         if @has_rows = 0 
  24793.         begin
  24794.             if exists (select 1 from ' + @basetable + ' (NOLOCK) , ' + @jointable + ' (NOLOCK) where '
  24795.  
  24796.     insert into #tempcmd (phase, cmdtext) values (8, @clause)
  24797.  
  24798.     set @clause = @filter_clause
  24799.     
  24800.     insert into #tempcmd (phase, cmdtext) values (8, @clause)
  24801.  
  24802.     set @clause = 
  24803.             ' and ' + @table + '.rowguidcol = @rowguid)    
  24804.                 select @has_rows = 1
  24805.         end
  24806. '
  24807.     insert into #tempcmd (phase, cmdtext) values (8, @clause)
  24808.  
  24809.     fetch next from f_c into @joinnick, @filter_clause
  24810.     end
  24811.  
  24812. close f_c
  24813. deallocate f_c
  24814.  
  24815. return(0)
  24816.  
  24817. Failure:
  24818.     close f_c
  24819.     deallocate f_c
  24820.     return(1)
  24821. go
  24822.  
  24823. exec dbo.sp_MS_marksystemobject sp_MSexclause  
  24824. grant exec on dbo.sp_MSexclause to public
  24825. go
  24826. raiserror('Creating procedure sp_MSgetcolordinalfromcolname', 0,1)
  24827. GO
  24828.  
  24829.  
  24830. -- @colname should not be quoted when the following procedure is called
  24831. create proc sp_MSgetcolordinalfromcolname @objid int, @sync_objid int, @colname sysname, @colordinal int OUTPUT  as
  24832.  
  24833.     declare @colid         int
  24834.     declare @objcolname sysname
  24835.     declare @iscomputed    tinyint
  24836.     declare @xtype        tinyint
  24837.  
  24838.     select @colid = min (colid) from syscolumns where id = @sync_objid and 
  24839.         name not in (select name from syscolumns where id=@objid and (iscomputed=1 OR type_name(xtype)='timestamp'))
  24840.         
  24841.     select @objcolname = name from syscolumns where id = @sync_objid and colid = @colid
  24842.     select @iscomputed=iscomputed, @xtype = xtype from syscolumns where id = @objid and name = @colname
  24843.     set @colordinal = 1
  24844.  
  24845.     while (@objcolname is not null and @objcolname <> @colname)
  24846.     begin
  24847.         if (@iscomputed=1 OR type_name(@xtype)='timestamp')
  24848.             goto Next_Column
  24849.  
  24850.     Next_Column:
  24851.         -- now set up to repeat the loop with the next column
  24852.         select @colid = min (colid) from syscolumns where id = @sync_objid and colid > @colid 
  24853.         
  24854.         set @objcolname = NULL
  24855.         if @colid is not null
  24856.             begin
  24857.                 select @objcolname = name from syscolumns where id = @sync_objid and colid = @colid
  24858.                 select @iscomputed=iscomputed, @xtype = xtype from syscolumns where id = @objid and name = @colname
  24859.             end
  24860.  
  24861.         set @colordinal = @colordinal + 1
  24862.     end
  24863.  
  24864.     return 0 
  24865. go
  24866.  
  24867. exec dbo.sp_MS_marksystemobject sp_MSgetcolordinalfromcolname  
  24868. go
  24869.  
  24870. grant exec on dbo.sp_MSgetcolordinalfromcolname to public
  24871. go
  24872.  
  24873. raiserror('Creating procedure sp_MSinsertbeforeimageclause', 0,1)
  24874. GO
  24875.  
  24876. create proc sp_MSinsertbeforeimageclause @pubid uniqueidentifier, @objid int, @tablenickstr nvarchar(12)  as
  24877.     set nocount on
  24878.     declare @cmdpiece nvarchar(4000)
  24879.     declare @before_objid int
  24880.     declare @sync_objid int
  24881.     declare @before_name sysname
  24882.     declare @collist nvarchar(4000)
  24883.     declare @vallist nvarchar(4000)
  24884.     declare @colname sysname
  24885.     declare @colordinal smallint
  24886.     declare @argname sysname
  24887.  
  24888.     -- Do we have a before table?
  24889.     select @before_objid = max(before_image_objid) from  sysmergearticles where objid = @objid and
  24890.             before_image_objid is not null
  24891.     select @before_name = OBJECT_NAME(@before_objid)
  24892.  
  24893.     select @sync_objid = sync_objid    from sysmergearticles where objid=@objid and pubid=@pubid
  24894.  
  24895.     if @before_name is null
  24896.         begin
  24897.             return 0
  24898.         end
  24899.  
  24900.     set @collist = ''
  24901.     -- Loop over columns to make the column list for the insert / select command
  24902.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name from syscolumns
  24903.     where id = @before_objid and name <> 'generation' and name <> 'system_delete' order by colid
  24904.     FOR READ ONLY
  24905.  
  24906.     open col_cursor
  24907.     set @vallist = ''
  24908.     fetch next from col_cursor into @colname
  24909.     while (@@fetch_status <> -1)
  24910.         begin
  24911.         --this column is not in vertical partitioning
  24912.         if not exists (select * from syscolumns where name=@colname and id=@sync_objid)
  24913.         begin
  24914.             fetch next from col_cursor into @colname
  24915.             continue
  24916.         end
  24917.         set @collist = @collist + QUOTENAME(@colname) + ', '
  24918.         exec sp_MSgetcolordinalfromcolname @objid, @sync_objid, @colname, @colordinal out
  24919.         select @argname = '@p' + rtrim(convert(nchar, @colordinal))
  24920.         set @vallist = @vallist + @argname + ', '
  24921.         fetch next from col_cursor into @colname
  24922.         end
  24923.     close col_cursor
  24924.     deallocate col_cursor
  24925.  
  24926.     -- Our list has all of the columns except generation since that gets set to a local variable
  24927.     -- Make the insert command
  24928.     set @cmdpiece = ' declare @gen_cur int select @gen_cur = max(gen_cur) from sysmergearticles where nickname = ' + @tablenickstr
  24929.     insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  24930.     --select @cmdpiece
  24931.  
  24932.     set @cmdpiece = ' insert into ' + QUOTENAME(@before_name) + ' ( ' + @collist +    
  24933.                     ' generation, system_delete) values (' + @vallist + ' @gen_cur, 1 )'
  24934.     insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  24935.     --select @cmdpiece
  24936.  
  24937.     return 0
  24938.     
  24939. go
  24940.  
  24941. exec dbo.sp_MS_marksystemobject sp_MSinsertbeforeimageclause  
  24942. go
  24943.  
  24944. grant exec on dbo.sp_MSinsertbeforeimageclause to public
  24945. go
  24946.  
  24947.  
  24948. raiserror('Creating procedure sp_MSmakeinsertproc', 0,1)
  24949. GO
  24950.  
  24951. -- This will be called by snapshot at publisher side and 
  24952. -- merge at the subscriber side, check for dbo permission
  24953. create procedure sp_MSmakeinsertproc 
  24954.     (@tablename sysname, @ownername sysname, @procname sysname, @pubid uniqueidentifier)
  24955. as
  24956. declare @argname            sysname
  24957. declare @id                 int
  24958. declare @sync_objid            int
  24959. declare @qualified_name        nvarchar(270)
  24960. declare @idstr                nvarchar(100)
  24961. declare @iscomputed            tinyint
  24962. declare @xtype                tinyint
  24963. declare @colstat             int
  24964. declare @permissions        int
  24965. declare @permissions_str     nvarchar(10)
  24966.  
  24967. if @ownername is NULL or @ownername=''
  24968.     select @qualified_name = QUOTENAME(@tablename)
  24969. else    
  24970.     select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
  24971.     
  24972. select @id = object_id(@qualified_name)
  24973. if @id is NULL return (1)
  24974.  
  24975. select @sync_objid = sync_objid, @permissions_str=convert(nvarchar(10),check_permissions), @permissions=check_permissions
  24976.     from sysmergearticles where objid=@id and pubid=@pubid
  24977.  
  24978. set @idstr = rtrim(convert(nchar, @id))    
  24979.  
  24980. declare @retcode int
  24981. declare @colname nvarchar(140)
  24982. declare @rgcolname nvarchar(140)
  24983. declare @typename nvarchar(140)
  24984. declare @colid smallint
  24985. declare @status tinyint
  24986. declare @len smallint
  24987. declare @prec int
  24988. declare @scale int
  24989. declare @tablenick int
  24990. declare @tablenickstr nvarchar(12)
  24991. declare @colordinal smallint
  24992. declare @cmdpiece nvarchar(4000)
  24993.  
  24994. set nocount on
  24995.  
  24996. -- Check for subscribing permission
  24997. exec @retcode=sp_MSreplcheck_subscribe
  24998. if @retcode<>0 or @@ERROR<>0 return (0)
  24999.     
  25000. execute @retcode = dbo.sp_MStablenickname @ownername, @tablename, @tablenick output
  25001. IF @@ERROR <> 0 or @retcode <>0 return (0)
  25002. set @tablenickstr = rtrim(convert(nchar, @tablenick))
  25003.  
  25004. -- create temp table to select the command text out of
  25005. create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25006.  
  25007. -- insert text pieces that don't repeat for each column
  25008.  
  25009. -- phase 0 : create procedure and fixed part of argument list
  25010. set @cmdpiece = 'create procedure dbo.'  + QUOTENAME(@procname) + ' (@rowguid uniqueidentifier, 
  25011.     @generation int, @lineage varbinary(255),  @colv varbinary(2048) '
  25012. insert into #tempcmd (phase, cmdtext) values (0, @cmdpiece)
  25013.  
  25014. -- phase 1 is rest of argument list; goes in during loop over columns
  25015. -- phase 2 : paren to close argument list, and variable declarations
  25016. set @cmdpiece = ') as
  25017.     declare @tablenick int
  25018.     declare @errcode int
  25019.     declare @retcode int
  25020.     declare @has_rows int
  25021.     
  25022.     set @has_rows = 0
  25023.     set nocount on
  25024.  
  25025.     set @errcode= 0
  25026.     
  25027.     if sessionproperty(''replication_agent'') = 0
  25028.     begin
  25029.         exec @retcode = dbo.sp_MSreplcheck_connection @objid = ' + @idstr + '
  25030.         if @retcode<>0 or @@ERROR<>0 return (3)
  25031.     end
  25032.     '
  25033.     if @permissions>0
  25034.         begin
  25035.             select @cmdpiece = @cmdpiece + ' exec @retcode = dbo.sp_MSreplcheck_permission @objid = ' + @idstr + ', @type = 1, @permissions = ' + @permissions_str + '
  25036.                 if @retcode<>0 or @@ERROR<>0 return (4)'
  25037.         end    
  25038.     select @cmdpiece = @cmdpiece + '
  25039.     select @tablenick = ' + @tablenickstr
  25040.  
  25041. insert into #tempcmd (phase, cmdtext) values (2, @cmdpiece)
  25042.  
  25043. -- phase 3 is optional set identity insert on, goes in during loop if needed
  25044. -- phase 4 is beginning a sub transaction, setting save point and starting insert statement
  25045. set @cmdpiece = '
  25046.     begin transaction
  25047.     save transaction sp_insproc
  25048.     if @metadata_type = 1 or @metadata_type = 5
  25049.     begin
  25050.         if not exists (select * from dbo.MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid and
  25051.                         lineage = @lineage_old)
  25052.         begin
  25053.             set @errcode= 2
  25054.  
  25055.             goto Failure
  25056.         end
  25057.     end
  25058.     exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage, @colv, 2, @tombstone_rows_deleted = @has_rows OUTPUT
  25059.     if @retcode<>0 or @@ERROR<>0
  25060.     begin
  25061.         set @errcode= 0
  25062.         goto Failure
  25063.     end
  25064.     insert into ' + @qualified_name + ' ('
  25065. insert into #tempcmd (phase, cmdtext) values (4, @cmdpiece)
  25066.  
  25067. -- phase 5 is column list that we are inserting; done in loop
  25068.  
  25069. -- phase 6 is just the opening and closing parens and VALUES keyword
  25070. set @cmdpiece = ') values ('
  25071. insert into #tempcmd (phase, cmdtext) values (6, @cmdpiece)
  25072.  
  25073. -- phase 7 is all of those arguments as the list of value expressions; done in loop
  25074. -- phase 8 finish insert, check status, etc.
  25075. -- if we have a permanent view, check for case where we inserted a row that doesn't
  25076. -- meet filters of subscriber we are getting the insert from
  25077. set @cmdpiece = ')
  25078.     if (@@rowcount <> 1)
  25079.     begin
  25080.         set @errcode= 3
  25081.         goto Failure
  25082.     end
  25083. '
  25084. insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  25085.  
  25086. -- only add the following code when creating proc at publisher
  25087. if exists (select 1 from sysmergepublications where  pubid=@pubid and LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name())
  25088. begin
  25089.     -- Add in pieces that check for inserting a row that instantly means other rows need to be downloaded
  25090.     -- If we insert such a row, set the generation and partchangegen so that we will download everything
  25091.     -- that needs to go.
  25092.  
  25093.     exec sp_MSexclause @tablenick, @pubid
  25094.     if @@error<>0 return(1)
  25095.  
  25096.     if exists (select * from sysmergearticles where pubid = @pubid and objid = @id and view_type = 1)
  25097.     begin
  25098.         /* Get name of rowguidcol. Aliasing doesn't work through a view. */
  25099.         select @rgcolname = QUOTENAME(name) from syscolumns where id = @id and ColumnProperty(@id, name, 'isrowguidcol') = 1
  25100.         if @rgcolname is null
  25101.             set @rgcolname = 'rowguid'
  25102.         select @cmdpiece = ' 
  25103.             if @has_rows = 0
  25104.                 begin
  25105.                     if not exists (select 1 from ' + QUOTENAME(OBJECT_NAME(sync_objid))
  25106.             from sysmergearticles where pubid = @pubid and objid = @id
  25107.         set @cmdpiece = @cmdpiece + ' where ' + @rgcolname + ' = @rowguid) 
  25108.                     begin
  25109.                         select @has_rows = 1 '
  25110.         insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  25111.  
  25112.         exec sp_MSinsertbeforeimageclause @pubid, @id, @tablenickstr
  25113.  
  25114.         set @cmdpiece = ' 
  25115.                     end    
  25116.                 end '
  25117.         insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  25118.     end
  25119. end
  25120. -- if we already have a tombstone for this row, (especially a remove from partial) then
  25121. -- make sure we will set the generation so that it goes on down to subscribers of republishers
  25122. -- for backward compatibility, for 7.0 subscribers we do not want @has_rows to be 1
  25123.  
  25124. set @cmdpiece = '
  25125.             if @has_rows > 0     
  25126.                 update dbo.MSmerge_contents set generation = 0, partchangegen = 0 
  25127.                     where rowguid = @rowguid and tablenick = @tablenick'
  25128. insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  25129.  
  25130. set @cmdpiece = '
  25131.  
  25132.     commit tran
  25133. '
  25134. insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)
  25135.  
  25136. -- phase 9 is setting identity insert off if needed; done in loop
  25137. -- phase 10 is returning our success / failure status
  25138. set @cmdpiece = '
  25139.  
  25140.     return(1)
  25141.     
  25142. Failure:
  25143.     rollback tran sp_insproc
  25144.     commit tran    
  25145.  
  25146.     return(@errcode)
  25147.     '
  25148. insert into #tempcmd (phase, cmdtext) values (10, @cmdpiece)
  25149.     
  25150. -- now loop over columns and insert missing command pieces
  25151.  
  25152. select @colid = min (colid) from syscolumns where id = @sync_objid and 
  25153.     name not in (select name from syscolumns where id=@id and (iscomputed=1 OR type_name(xtype)='timestamp'))
  25154.     
  25155. select @colname = QUOTENAME(name), @typename = type_name(xtype),
  25156.     @len = length,     @prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
  25157.     from syscolumns 
  25158.     where id = @sync_objid and colid = @colid
  25159. select @status = status, @iscomputed=iscomputed, @xtype=xtype, @colstat=colstat from syscolumns 
  25160.     where id = @id and QUOTENAME(name) = @colname
  25161. if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  25162.     select @len = @len/2
  25163. set @colordinal = 1
  25164.  
  25165. while (@colname is not null)
  25166.     begin
  25167.     if (@iscomputed=1 OR type_name(@xtype)='timestamp')
  25168.         goto Next_Column
  25169.     exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  25170.     if @@error<>0 OR @retcode <>0 return (1)
  25171.  
  25172.     select @argname = '@p' + rtrim(convert(nchar, @colordinal))
  25173.     -- add to argument list (phase 1)
  25174.     set @cmdpiece = ', ' + @argname + ' ' + @typename
  25175.     insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece)
  25176.  
  25177.     -- add to column list and value list
  25178.     if (@colordinal = 1)
  25179.         begin
  25180.         -- column list is phase 5
  25181.         set @cmdpiece = @colname
  25182.         insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)
  25183.  
  25184.         -- argname for values list is phase 7
  25185.         set @cmdpiece = @argname
  25186.         insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
  25187.         end
  25188.     else
  25189.         begin
  25190.         -- column list is phase 5; need preceding comma since not the first one.
  25191.         set @cmdpiece = ', ' + @colname
  25192.         insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)
  25193.  
  25194.         -- argname for values list is phase 7 need preceding comma since not the first one.
  25195.         set @cmdpiece = ', ' + @argname
  25196.         insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
  25197.         end
  25198.         
  25199.     -- is this an identity column without 'not for replication' marking?
  25200.     if (@status = 128) and (@colstat & 0x0008 =0)
  25201.         begin
  25202.         -- turning identity insert on is phase 3
  25203.         set @cmdpiece = '
  25204.     set identity_insert ' + @qualified_name + ' on'
  25205.         insert into #tempcmd (phase, cmdtext) values (3, @cmdpiece)
  25206.  
  25207.         -- turning identity insert on is phase 9
  25208.         set @cmdpiece = '
  25209.     set identity_insert ' + @qualified_name + ' off'
  25210.         insert into #tempcmd (phase, cmdtext) values (9, @cmdpiece)
  25211.         end
  25212.  
  25213. Next_Column:
  25214.     -- now set up to repeat the loop with the next column
  25215.     select @colid = min (colid) from syscolumns where id = @sync_objid and colid > @colid 
  25216.         
  25217.     set @colname = NULL
  25218.     if @colid is not null
  25219.         select @colname = QUOTENAME(name), @status = status, @typename = type_name(xtype), @len = length,
  25220.         @prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
  25221.         from syscolumns where id = @sync_objid and colid = @colid
  25222.     select @status = status, @iscomputed=iscomputed, @xtype=xtype,@colstat=colstat from syscolumns 
  25223.         where id = @id and QUOTENAME(name) = @colname
  25224.         
  25225.     if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  25226.         select @len = @len/2
  25227.     set @colordinal = @colordinal + 1
  25228.     end
  25229.  
  25230.     select @cmdpiece = ',@metadata_type tinyint = NULL, @lineage_old varbinary(255) = NULL'
  25231.     insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece)
  25232.     
  25233. -- Now we select out the command text pieces in proper order so that our caller,
  25234. -- xp_execresultset will execute the command that creates the stored procedure.
  25235.  
  25236. select cmdtext from #tempcmd order by phase, step
  25237. drop table #tempcmd
  25238. go
  25239.  
  25240. exec dbo.sp_MS_marksystemobject sp_MSmakeinsertproc 
  25241. go
  25242. grant exec on dbo.sp_MSmakeinsertproc to public
  25243. go
  25244.  
  25245. raiserror('Creating procedure sp_MSmakeupdateproc', 0,1)
  25246. GO
  25247.  
  25248. -- This will be called by snapshot at publisher side and 
  25249. -- merge at the subscriber side, check for dbo permission
  25250. create procedure sp_MSmakeupdateproc 
  25251.     (@tablename sysname, @ownername sysname, @procname sysname, @pubid uniqueidentifier)
  25252. as
  25253. declare @retcode             int
  25254. declare @argname            nvarchar(10)
  25255. declare @varname            nvarchar(10)
  25256. declare @cmdpiece            nvarchar(4000)
  25257. declare @qualified_name        nvarchar(270)
  25258. declare @littlecomp            nvarchar(300)
  25259. declare @id                    int
  25260. declare @sync_objid            int
  25261. declare @idstr                nvarchar(100) 
  25262. declare @fast_multicol_updateproc_bit bit
  25263. declare @permissions_str    nvarchar(10)
  25264. declare @permissions        int
  25265.  
  25266. set nocount on
  25267.  
  25268. if @ownername is NULL or @ownername=''
  25269.     select @qualified_name = QUOTENAME(@tablename)
  25270. else    
  25271.     select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
  25272.  
  25273. select @id = object_id(@qualified_name)
  25274.     if @id is NULL return (1)
  25275.  
  25276. select @sync_objid = sync_objid, @fast_multicol_updateproc_bit = fast_multicol_updateproc, @permissions=check_permissions,
  25277.         @permissions_str=convert(nvarchar(10), check_permissions) from sysmergearticles 
  25278.         where objid=@id and pubid = @pubid
  25279.     
  25280. set @idstr = rtrim(convert(nchar, @id))    
  25281.  
  25282. declare @colname nvarchar(140)
  25283. declare @typename nvarchar(140)
  25284. declare @colid smallint
  25285. declare @colordinal smallint
  25286. declare @colordstr nvarchar(4)
  25287. declare @xtype        tinyint
  25288. declare @iscomputed tinyint
  25289. declare @isrowguidcol tinyint
  25290. declare @separate_update_needed tinyint
  25291. declare @update_stmt_started tinyint
  25292. declare @status tinyint
  25293. declare @len smallint
  25294. declare @blen smallint
  25295. declare @prec int
  25296. declare @scale int
  25297. declare @tablenick int
  25298. declare @tablenickstr nvarchar(12)
  25299. declare @bytestr      nvarchar(10)
  25300. declare @byteordinal  smallint
  25301. declare @numbytes      smallint
  25302. declare @bitstr       nvarchar(10)
  25303. declare @colpat          nvarchar(130)
  25304. declare @has_updateable_columns_in_select_list bit
  25305. select @separate_update_needed = 0
  25306. select @update_stmt_started = 0
  25307. select @has_updateable_columns_in_select_list = 0
  25308.     /*
  25309.     ** Check for dbo permission
  25310.     */
  25311.     exec @retcode=sp_MSreplcheck_subscribe
  25312.     if @retcode<>0 or @@ERROR<>0 return (1)
  25313.     
  25314. execute @retcode = dbo.sp_MStablenickname @ownername, @tablename, @tablenick output
  25315. if @@ERROR <>0 OR @retcode <>0 return (1)
  25316. set @tablenickstr = rtrim(convert(nchar, @tablenick))
  25317.  
  25318. -- create temp table to select the command text out of
  25319. create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25320.  
  25321. -- insert text pieces that don't repeat for each column
  25322.  
  25323. -- phase 0 : create procedure and fixed part of argument list
  25324. set @cmdpiece = 'Create procedure dbo.' + @procname + ' (@rowguid uniqueidentifier, @setbm varbinary(125) = NULL,
  25325.     @metadata_type tinyint, @lineage_old varbinary(255), @generation int,
  25326.     @lineage_new varbinary(255), @colv varbinary(2048) '
  25327. insert into #tempcmd (phase, cmdtext) values (0, @cmdpiece)
  25328.  
  25329. -- phase 1 is rest of argument list; goes in during loop over columns
  25330. -- phase 2 paren to close argument list and fixed variable declarations
  25331. set @cmdpiece = ') as
  25332.     declare @tablenick int
  25333.     declare @errcode int
  25334.     declare @fset int
  25335.     declare @match int
  25336.     declare @retcode smallint
  25337.     set nocount on
  25338.  
  25339.     if sessionproperty(''replication_agent'') = 0
  25340.     begin
  25341.         exec @retcode = dbo.sp_MSreplcheck_connection @objid = ' + @idstr + '
  25342.         if @retcode<>0 or @@ERROR<>0 return (3)
  25343.     end
  25344.     '
  25345.     if @permissions>0
  25346.         begin
  25347.         select @cmdpiece=@cmdpiece + '
  25348.             exec @retcode = dbo.sp_MSreplcheck_permission @objid = ' + @idstr + ', @type=2, @permissions = ' + @permissions_str + '
  25349.             if @retcode<>0 or @@ERROR<>0 return (4)'
  25350.         end
  25351.  
  25352.     select @cmdpiece = @cmdpiece + '
  25353.     select @tablenick = ' + @tablenickstr
  25354.  
  25355. insert into #tempcmd (phase, cmdtext) values (2, @cmdpiece)
  25356.  
  25357. -- phase 3 is rest of variable declarations; goes in during loop over columns
  25358. -- phase 4 begin a transaction, set savepoint in case we roll back, begin select to get current values
  25359. set @cmdpiece = '    begin transaction sub
  25360.     save transaction sub
  25361.     select '
  25362. insert into #tempcmd (phase, cmdtext) values (4, @cmdpiece)
  25363.  
  25364. -- phase 5 is middle part of select assigning column values to local variables -- goes in loop
  25365. -- phase 6 -- finish the select, check that metadata matches
  25366. set @cmdpiece = '    from ' + @qualified_name + ' (updlock) where rowguidcol = @rowguid
  25367.     exec @retcode= dbo.sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
  25368.     if @retcode<>0 or @@ERROR<>0
  25369.     begin
  25370.         set @errcode= 3
  25371.         goto Failure
  25372.     end
  25373.     if (@match = 1)
  25374.     begin
  25375. '
  25376. insert into #tempcmd (phase, cmdtext) values (6, @cmdpiece)
  25377.  
  25378. -- phase 7 is a bunch of if's that compare old values with new values ; goes in during loop
  25379. -- phase 8 finish the stored procedure
  25380. set @cmdpiece = '        exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, @colv, 2
  25381.         if @retcode<>0 or @@ERROR<>0
  25382.         begin
  25383.             set @errcode= 3
  25384.             goto Failure
  25385.         end
  25386.     end
  25387.     else
  25388.     begin
  25389.         set @errcode= 2
  25390.         goto Failure
  25391.     end
  25392.  
  25393.     commit transaction
  25394.  
  25395.  
  25396.     return(1)
  25397.  
  25398. Failure:
  25399.     rollback transaction sub
  25400.     commit transaction
  25401.  
  25402.     return @errcode'
  25403. insert into #tempcmd (phase, cmdtext) values (11, @cmdpiece)
  25404.  
  25405. -- now do the loop over all columns and insert the missing pieces
  25406.  
  25407. -- don't script out computed columns or timestamp columns
  25408. select @colid = min (colid) from syscolumns where id = @sync_objid and 
  25409.     name not in (select name from syscolumns where id=@id and (iscomputed=1 OR type_name(xtype)='timestamp'))
  25410. select @colname = NULL
  25411. select @colname = name, @typename = type_name(xtype), @blen = length,
  25412.     @prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
  25413.     from syscolumns 
  25414.     where id = @sync_objid and colid = @colid
  25415. select @status = status, @iscomputed=iscomputed, @xtype=xtype,
  25416.     @isrowguidcol = COLUMNPROPERTY(id, name, 'IsRowGuidCol')
  25417.     from syscolumns 
  25418.     where id = @id and name = @colname
  25419.  
  25420. -- get col count to determine what size our bitmask is going to be
  25421. declare @colcount int
  25422. select @colcount = count(*) from syscolumns where id = @sync_objid and 
  25423.     name not in (select name from syscolumns where id=@id and (iscomputed=1 OR type_name(xtype)='timestamp'))    
  25424.  
  25425. set @cmdpiece = '        
  25426.     declare @colbitmask binary(' + convert(nvarchar,1+(@colcount-1) / 8) + ') 
  25427.     select @colbitmask = 0
  25428.     '
  25429.  
  25430. select @numbytes = 1+(@colcount-1) / 8
  25431. insert into #tempcmd (phase, cmdtext) values (2, @cmdpiece)
  25432.  
  25433. if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  25434.     set @len = @blen/2
  25435. else
  25436.     set @len = @blen
  25437. set @colordinal = 1
  25438.  
  25439. declare @firstCol tinyint
  25440. set @firstCol= 1
  25441.  
  25442. while (@colname is not null)
  25443. begin
  25444.     
  25445.     set @colordstr = convert(nvarchar(4), @colordinal)
  25446.     exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  25447.     if @@ERROR <>0 OR @retcode <>0 return (1)
  25448.  
  25449.     if (@fast_multicol_updateproc_bit = 1)
  25450.     begin
  25451.         
  25452.         -- check if separate update statement is needed only if article supports fast multi-column updates.
  25453.  
  25454.         -- reset @separate_update_needed
  25455.         set @separate_update_needed = 0
  25456.     
  25457.         --check if this column is part of the filter or join filter clause.
  25458.         -- if so, use a separater update statement for it rather than setting bitmask for the one cumulative update statement.
  25459.         set @colpat = '%' + @colname + '%'
  25460.         -- does updating this column change membership in a partial replica? 
  25461.         if exists (select * from sysmergearticles where objid = @id and subset_filterclause like @colpat)
  25462.             set @separate_update_needed = 1
  25463.         else if exists (select * from sysmergesubsetfilters where art_nickname = @tablenick and join_filterclause like @colpat)
  25464.             set @separate_update_needed = 1
  25465.         else if exists (select * from sysmergesubsetfilters where join_nickname = @tablenick and join_filterclause like @colpat)
  25466.             set @separate_update_needed = 1
  25467.         else if (@typename = 'ntext' or @typename = 'text' or @typename = 'image')
  25468.             set @separate_update_needed = 1
  25469.     end
  25470.     else
  25471.     begin
  25472.         set @separate_update_needed = 1            -- separate update statement for each column.
  25473.     end
  25474.     
  25475.     if @status = 128 OR @iscomputed=1 OR type_name(@xtype)='timestamp'
  25476.         goto Next_Column
  25477.  
  25478.     set @colname = QUOTENAME(@colname)
  25479.  
  25480.     -- put in argument list element (phase 1)
  25481.     set @argname = '@p' + rtrim(@colordstr)
  25482.  
  25483.     set @cmdpiece = ',
  25484.         ' + @argname + ' ' + @typename + ' = NULL '
  25485.  
  25486.     insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece)
  25487.  
  25488.     if (@isrowguidcol = 1)
  25489.         goto Next_Column
  25490.  
  25491.     if (@separate_update_needed = 0)
  25492.     begin
  25493.         
  25494.         select @bytestr = convert( nvarchar, 1 + (@colordinal-1) / 8 )
  25495.         select @byteordinal = 1 + (@colordinal-1) / 8
  25496.         select @bitstr =  convert( nvarchar, power(2, (@colordinal-1) % 8 ) )
  25497.  
  25498.         if (@update_stmt_started = 0)
  25499.         begin
  25500.             select @update_stmt_started = 1
  25501.             select @cmdpiece = 'update ' + @qualified_name + ' set '
  25502.             insert into #tempcmd (phase, cmdtext) values (8, @cmdpiece)        -- goes after phase 7
  25503.             select @cmdpiece = ' where rowguidcol = @rowguid 
  25504.                 if (@@rowcount <> 1)
  25505.                 begin
  25506.                     set @errcode= 3
  25507.                     goto Failure
  25508.                 end'
  25509.             insert into #tempcmd (phase, cmdtext) values (10, @cmdpiece)    -- goes after phase 9 which would be the SET clause for different columns
  25510.         end
  25511.         else
  25512.         begin
  25513.             select @cmdpiece = ','
  25514.             insert into #tempcmd (phase, cmdtext) values (9, @cmdpiece)
  25515.         end
  25516.  
  25517.         select @cmdpiece = @colname + ' = case substring(@colbitmask,' + @bytestr + ',1) & ' + @bitstr + ' when ' + @bitstr + ' then ' + @argname + ' else ' + @colname + ' end '
  25518.         insert into #tempcmd (phase, cmdtext) values (9, @cmdpiece)
  25519.     end
  25520.  
  25521.     -- put in declaration for variable (phase 3) -- text and image get no variable
  25522.     if (@typename <> 'ntext' and @typename <> 'text' and @typename <> 'image')
  25523.     begin
  25524.         set @varname = '@l' + rtrim(@colordstr)
  25525.  
  25526.         set @cmdpiece = 'declare ' + @varname + ' ' + @typename + '
  25527. '
  25528.         insert into #tempcmd (phase, cmdtext) values (3, @cmdpiece)
  25529.  
  25530.         -- put in set piece to initialize variable to old value in select statement (phase 5)
  25531.         if @firstCol=1
  25532.         begin
  25533.             set @cmdpiece= ''
  25534.             set @firstCol= 0
  25535.         end
  25536.         else
  25537.             set @cmdpiece= ', '
  25538.  
  25539.         set @cmdpiece = @cmdpiece + @varname + ' = ' + @colname
  25540.         insert into #tempcmd (phase, cmdtext) values (5, @cmdpiece)
  25541.  
  25542.         -- put in if piece that compares old value with new, checks bit if argument is null
  25543.         if (@typename like '%char%')
  25544.         begin
  25545.             -- Compare binaries instead of variables so that case changes are caught as different
  25546.             set @littlecomp = 'convert(varbinary(' + rtrim(convert(nchar, @blen)) + '), ' + @argname + ')
  25547.                 = convert(varbinary(' + rtrim(convert(nchar, @blen)) + '), ' + @varname + ')'
  25548.         end
  25549.         else
  25550.         begin
  25551.             set @littlecomp = @argname + ' = ' + @varname
  25552.         end
  25553.  
  25554.         set @cmdpiece = '            if ' + @littlecomp + '
  25555.                 set @fset = 0
  25556.             else if ( ' + @varname + ' is null and ' + @argname + ' is null) 
  25557.                 set @fset = 0
  25558.             else if ' + @argname + ' is not null
  25559.                 set @fset = 1
  25560.             else if @setbm = 0x0
  25561.                 set @fset = 0
  25562.             else
  25563.                 exec @fset = dbo.sp_MStestbit @setbm, ' + @colordstr + '
  25564.             if @fset <> 0
  25565.                 begin
  25566.                 '
  25567.         insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
  25568.  
  25569.         if (@separate_update_needed = 0)
  25570.         begin
  25571.             if (@numbytes = 1)
  25572.             begin
  25573.                 -- no bytes on left or right of the byte being bitwise OR-ed.
  25574.                 set @cmdpiece = '
  25575.                     select @colbitmask = convert(varbinary(1), substring(@colbitmask, ' + @bytestr + ' , 1) | ' + @bitstr + ')
  25576.                     end
  25577.                     '
  25578.             end
  25579.             else 
  25580.             begin
  25581.                 -- there could be byte(s) on left and/or right of byte being bitwise OR-ed.
  25582.                 set @cmdpiece = '
  25583.                 select @colbitmask = 
  25584.                     convert
  25585.                     (
  25586.                     varbinary(' + convert(nvarchar, @numbytes) + '), '
  25587.                     + case when (@byteordinal = 1) then '' else ' convert(varbinary(' + convert(nvarchar, @byteordinal-1) + '), substring(@colbitmask, 1, ' + convert(nvarchar, @byteordinal-1) + ')) +' end +
  25588.                     ' convert(varbinary(1), substring(@colbitmask, ' + @bytestr + ' , 1) | ' + @bitstr + ') '
  25589.                     + case when (@byteordinal = @numbytes) then '' else ' + convert(varbinary(' + convert(nvarchar, @numbytes - @byteordinal) + '), substring(@colbitmask, ' + convert(nvarchar, @byteordinal+1) + ', ' + convert(nvarchar, @numbytes - @byteordinal) + ')) ' end + '
  25590.                     )
  25591.                 end 
  25592.                 '
  25593.             end
  25594.         end
  25595.         else
  25596.         begin
  25597.             set @cmdpiece = '
  25598.                     update ' + @qualified_name + ' set ' + @colname + ' = ' + @argname + ' where rowguidcol = @rowguid 
  25599.                     if (@@rowcount <> 1)
  25600.                     begin
  25601.                         set @errcode= 3
  25602.                         goto Failure
  25603.                     end
  25604.                 end 
  25605.                 '
  25606.         end
  25607.         insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)
  25608.         select @has_updateable_columns_in_select_list = 1
  25609.     end
  25610.     else
  25611.     begin
  25612.         -- for text and image, we just test if argument is null and whether bit is set
  25613.         -- build conditional update (phase 7)
  25614.         set @cmdpiece =  '            if ' + @argname + ' is not null
  25615.                 set @fset = 1
  25616.             else if @setbm = 0x0
  25617.                 set @fset = 0
  25618.             else 
  25619.                 exec @fset = dbo.sp_MStestbit @setbm, ' + @colordstr + '
  25620.             if @fset <> 0
  25621.                 begin
  25622.                     update ' + @qualified_name + ' set ' + @colname + ' = ' + @argname + ' where rowguidcol = @rowguid 
  25623.                     if (@@rowcount <> 1)
  25624.                     begin
  25625.                         set @errcode= 3
  25626.                         goto Failure
  25627.                     end
  25628.                 end 
  25629.             '
  25630.         -- Now insert the command to temp table
  25631.         insert into #tempcmd (phase, cmdtext) values (7, @cmdpiece)    
  25632.     end
  25633.     
  25634. Next_Column:        
  25635.     -- Advance loop to next column and repeat!
  25636.     select @colid = min (colid) from syscolumns where id = @sync_objid and colid > @colid and
  25637.         name not in (select name from syscolumns where id=@id and (iscomputed=1 OR type_name(xtype)='timestamp'))
  25638.     set @colname = NULL
  25639.     if (@colid is not null)
  25640.     begin
  25641.         select @colname = name, @typename = type_name(xtype), @blen = length,
  25642.             @prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale
  25643.             from syscolumns 
  25644.             where id = @sync_objid and colid = @colid
  25645.         select @status = status, @iscomputed=iscomputed, @xtype=xtype,
  25646.             @isrowguidcol = COLUMNPROPERTY(id, name, 'IsRowGuidCol') 
  25647.             from syscolumns 
  25648.             where id = @id and name = @colname
  25649.         
  25650.         if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  25651.             set @len = @blen/2
  25652.         else
  25653.             set @len = @blen
  25654.         set @colordinal = @colordinal + 1
  25655.     end
  25656. end
  25657.  
  25658. -- Add dummy column list to select statement if there is no user updateable 
  25659. -- column.
  25660. if @has_updateable_columns_in_select_list = 0
  25661. begin
  25662.     insert into #tempcmd (phase, cmdtext) values (3, N'declare @l int')
  25663.     insert into #tempcmd (phase, cmdtext) values (5, N'@l = 1')
  25664. end
  25665.  
  25666. -- Now we select out the command text pieces in proper order so that our caller,
  25667. -- xp_execresultset will execute the command that creates the stored procedure.
  25668.  
  25669. select cmdtext from #tempcmd order by phase, step
  25670. drop table #tempcmd
  25671. go
  25672.  
  25673. exec dbo.sp_MS_marksystemobject sp_MSmakeupdateproc 
  25674. go
  25675. grant exec on dbo.sp_MSmakeupdateproc to public
  25676. go
  25677.  
  25678. raiserror('Creating procedure sp_MSmakeselectproc', 0,1)
  25679. GO
  25680.  
  25681. SET ANSI_NULLS ON 
  25682. SET QUOTED_IDENTIFIER ON
  25683. GO
  25684. create procedure sp_MSmakeselectproc 
  25685.     (@tablename sysname, @ownername sysname, @procname sysname, @pubid uniqueidentifier)
  25686. as
  25687. declare @retcode            smallint
  25688. declare @argname            nvarchar(10)
  25689. declare @varname            nvarchar(10)
  25690. declare @columns            varbinary(128)
  25691. declare @cmdpiece           nvarchar(4000)
  25692. declare @qualified_name     nvarchar(270)
  25693. declare @column_list        table (line_no int identity(1,1) primary key, line nvarchar(4000))
  25694. declare @littlecomp nvarchar(300)
  25695. declare @colid              int
  25696. declare @col_name           nvarchar(140)
  25697. declare @id                 int
  25698. declare @idstr              nvarchar(100)
  25699. declare @sync_objid         int
  25700. set nocount on
  25701.  
  25702. if @ownername is NULL or @ownername=''
  25703.     select @qualified_name = QUOTENAME(@tablename)
  25704. else    
  25705.     select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename)
  25706.  
  25707. select @id = object_id(@qualified_name)
  25708.  
  25709. select @sync_objid=sync_objid from sysmergearticles where objid = @id and pubid=@pubid
  25710.  
  25711. set @idstr = rtrim(convert(nchar, @id)) 
  25712.  
  25713. /*
  25714. ** Include computed columns.
  25715. */
  25716. IF EXISTS (select name from syscolumns where id = @id and (name not in 
  25717.     (select name from syscolumns where id = @sync_objid)))
  25718.     OR exists (select name from syscolumns where id=@id and iscomputed=1)
  25719.     OR ObjectProperty(@id, 'TableHasTimestamp') = 1 
  25720. BEGIN
  25721.     DECLARE column_cursor CURSOR LOCAL FAST_FORWARD FOR
  25722.         select name from syscolumns where id=@id 
  25723.                 and iscomputed<>1 
  25724.                 and type_name(xtype) <>'timestamp' 
  25725.                 and name in (select name from syscolumns where id=@sync_objid)
  25726.     FOR READ ONLY
  25727.     open column_cursor
  25728.     fetch next from column_cursor into @col_name
  25729.     WHILE (@@fetch_status <> -1)
  25730.     BEGIN
  25731.             if ColumnProperty(@id, @col_name, 'isrowguidcol') = 1
  25732.                 select @col_name='rowguidcol'
  25733.             else
  25734.                 set @col_name = QUOTENAME(@col_name)
  25735.             if (select count(*) from @column_list) = 0
  25736.                 insert into @column_list(line) values (@col_name + '
  25737. ')
  25738.             else
  25739.                 insert into @column_list(line) values (', ' + @col_name + '
  25740. ')
  25741.             fetch next from column_cursor into @col_name            
  25742.     END
  25743.     close column_cursor
  25744.     deallocate column_cursor
  25745.  
  25746.     if (select count(*) from @column_list) = 0
  25747.     begin
  25748.         RAISERROR(21125, 16, -1)
  25749.         return (1)
  25750.     end
  25751. END
  25752. else 
  25753.     insert into @column_list(line) values('t.*')
  25754.  
  25755. /*
  25756. ** Check for dbo permission
  25757. */
  25758.     exec @retcode=sp_MSreplcheck_subscribe
  25759.     if @retcode<>0 or @@ERROR<>0 return (1)
  25760.  
  25761. set @cmdpiece= 'SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON'
  25762. exec (@cmdpiece)
  25763. if @@error<>0 return(1)
  25764.  
  25765. -- create temp table to select the command text out of
  25766. create table #tempcmd (step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25767.  
  25768. select @cmdpiece = '
  25769. Create procedure dbo.'  + QUOTENAME(@procname) + ' (@type int output, @rowguid uniqueidentifier=NULL) AS
  25770.     declare @retcode    int
  25771.         
  25772.     set nocount on
  25773.         
  25774.     if sessionproperty(''replication_agent'') = 0
  25775.     begin       
  25776.         exec @retcode = dbo.sp_MSreplcheck_connection @objid= ' + @idstr + '
  25777.         if @@ERROR<>0 or @retcode<>0 
  25778.             return (1)
  25779.     end
  25780.         
  25781.     if @type = 1
  25782.     begin
  25783.         select ' 
  25784. insert into #tempcmd (cmdtext) values (@cmdpiece)
  25785. insert into #tempcmd (cmdtext) select line from @column_list where line_no = 1
  25786. insert into #tempcmd (cmdtext) select 
  25787. '               ' + line from @column_list where line_no > 1 order by line_no asc
  25788. select @cmdpiece='              from ' + @qualified_name + ' t where rowguidcol = @rowguid
  25789.         if @@ERROR<>0 return(1)
  25790.     end
  25791.             
  25792.     else if @type < 4
  25793.     begin
  25794.         select c.tablenick, c.rowguid, c.generation, c.lineage, c.colv1
  25795.                ,' 
  25796. insert into #tempcmd (cmdtext) values (@cmdpiece)
  25797. insert into #tempcmd (cmdtext) select line from @column_list where line_no = 1
  25798. insert into #tempcmd (cmdtext) select 
  25799. '              ' + line from @column_list where line_no > 1 order by line_no asc
  25800. select @cmdpiece='          from ' +
  25801.                  @qualified_name + ' t,  #cont c where
  25802.                t.rowguidcol = c.rowguid
  25803.          order by t.rowguidcol 
  25804.         if @@ERROR<>0 return(1)
  25805.     end
  25806.  
  25807.     else if @type = 4
  25808.     begin
  25809.         set @type = 0
  25810.         if exists (select * from ' + @qualified_name + ' where rowguidcol = @rowguid)
  25811.             set @type = 3
  25812.         if @@ERROR<>0 return(1)
  25813.     end
  25814.  
  25815.     else if @type = 5
  25816.     begin
  25817.         delete ' + @qualified_name + ' where rowguidcol = @rowguid
  25818.         if @@ERROR<>0 return(1)
  25819.     end
  25820.  
  25821.     else if @type = 6 -- sp_MSenumcolumns
  25822.     begin
  25823.         select ' 
  25824. insert into #tempcmd (cmdtext) values (@cmdpiece)
  25825. insert into #tempcmd (cmdtext) select line from @column_list where line_no = 1
  25826. insert into #tempcmd (cmdtext) select 
  25827. '               ' + line from @column_list where line_no > 1 order by line_no asc
  25828. select @cmdpiece='              from ' + @qualified_name + ' t where 1=2
  25829.         if @@ERROR<>0 return(1)
  25830.     end
  25831.  
  25832.     else if @type = 7 -- sp_MSlocktable
  25833.     begin
  25834.         select 1 from ' + @qualified_name + '(tablock holdlock) where 1 = 2
  25835.         if @@ERROR<>0 return(1)
  25836.     end
  25837.  
  25838.     else if @type = 8 -- put update lock
  25839.     begin
  25840.         if not exists (select * from ' + @qualified_name + '(UPDLOCK HOLDLOCK) where rowguidcol = @rowguid)
  25841.         begin
  25842.             RAISERROR(20031 , 16, -1)
  25843.             return(1)
  25844.         end
  25845.     end
  25846.         
  25847.     return(0)'
  25848.  
  25849. insert into #tempcmd (cmdtext) values (@cmdpiece)
  25850. select cmdtext from #tempcmd order by step
  25851. drop table #tempcmd
  25852. go
  25853.             
  25854. exec dbo.sp_MS_marksystemobject sp_MSmakeselectproc 
  25855. go
  25856. grant exec on dbo.sp_MSmakeselectproc to public
  25857. go
  25858.  
  25859. SET ANSI_NULLS OFF
  25860. go
  25861. raiserror('Creating procedure sp_MSdropconstraints', 0,1)
  25862. GO
  25863.  
  25864. -- This will be called merge at the subscriber side, check for dbo permission
  25865. create procedure sp_MSdropconstraints
  25866.       @table sysname
  25867. as
  25868.     declare @const_name nvarchar(140)
  25869.     declare @objid int
  25870.     declare @retcode int
  25871.     
  25872.     /*
  25873.     ** Check for subscribing permission
  25874.     */
  25875.     exec @retcode=sp_MSreplcheck_subscribe
  25876.     if @retcode<>0 or @@ERROR<>0 return (1)
  25877.  
  25878.     select @table=QUOTENAME(@table)
  25879.     
  25880.     set @objid = object_id(@table)
  25881.     if @objid is null
  25882.         select @objid = id from sysobjects where name=@table
  25883.     if @objid is NULL
  25884.         return (1)
  25885.     select @const_name = QUOTENAME(object_name(constid)) from 
  25886.         sysreferences where fkeyid = @objid
  25887.     while @const_name is not null
  25888.         begin
  25889.             exec ('alter table ' + @table +
  25890.                 ' drop constraint ' + @const_name)
  25891.             if @@ERROR <> 0
  25892.                 return (1)
  25893.             set @const_name = NULL
  25894.             select @const_name = QUOTENAME(object_name(constid)) from 
  25895.                 sysreferences where fkeyid = @objid
  25896.         end
  25897.  
  25898.     return (0)        
  25899. go
  25900.  
  25901. exec dbo.sp_MS_marksystemobject sp_MSdropconstraints
  25902. go
  25903. grant exec on dbo.sp_MSdropconstraints to public
  25904. go
  25905.  
  25906. raiserror('Creating procedure sp_MSinsertschemachange', 0,1)
  25907. GO
  25908.  
  25909. CREATE PROCEDURE sp_MSinsertschemachange(
  25910.     @pubid            uniqueidentifier,
  25911.     @artid            uniqueidentifier = NULL, /* Can be NULL for directory commands */
  25912.     @schemaversion     int,
  25913.     @schemaguid        uniqueidentifier,
  25914.     @schematype        int,
  25915.     @schematext        nvarchar(2000)
  25916.     )
  25917. as
  25918.     declare @retcode            int
  25919.     declare @constraintname        sysname    
  25920.     declare @owner                sysname
  25921.     declare @tablename            sysname
  25922.     declare @qualname            nvarchar(270)
  25923.     declare @objid                int
  25924.     declare @alter_table_type    int
  25925.     /*
  25926.     ** Check for subscribing permission
  25927.     */
  25928.     exec @retcode=sp_MSreplcheck_subscribe
  25929.     if @retcode<>0 or @@ERROR<>0 return (1)
  25930.     
  25931.     select @alter_table_type = 11
  25932.     
  25933.     /* Parameter validation */
  25934.     if (@schemaversion is null)
  25935.         begin
  25936.         RAISERROR(14043, 16, -1, '@schemaversion')
  25937.         return (1)
  25938.         end
  25939.  
  25940.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  25941.         begin
  25942.         RAISERROR(20054 , 16, -1)
  25943.         return (1)
  25944.         end
  25945.  
  25946.     /*
  25947.     ** Special case: for push subscription, reinit-with-upload, we do not want to cleanup subscriber side
  25948.     ** cause we need to upload; however we still need to apply alter-table. To avoid duplicate key insert
  25949.     ** failure, we no-OP this insert of alter-table schema.
  25950.     */
  25951.     if @schematype=@alter_table_type and exists 
  25952.         (select * from sysmergeschemachange where pubid=@pubid and schemaversion=@schemaversion)
  25953.         return (1)
  25954.         
  25955.  
  25956.     insert into sysmergeschemachange with (HOLDLOCK TABLOCKX) (pubid, artid, schemaversion, schemaguid, schematype, schematext)
  25957.              values (@pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext) 
  25958.     if @@error <> 0        
  25959.         begin
  25960.             RAISERROR(21305 , 16, -1)
  25961.             return (1)
  25962.         end
  25963.     /* update the schema version and schemaguid in MSmerge_replinfo */        
  25964.     declare @my_nickname int
  25965.     declare @srvid int
  25966.     select @srvid = 0
  25967.     declare @repid         uniqueidentifier
  25968.     select  @my_nickname = replnickname,  @repid = repid from MSmerge_replinfo 
  25969.         where repid in (select subid from sysmergesubscriptions
  25970.             where srvid = @srvid and db_name = DB_NAME() and pubid = @pubid)
  25971.  
  25972.     update MSmerge_replinfo set schemaversion = @schemaversion, schemaguid = @schemaguid where repid = @repid and (schemaversion<@schemaversion or schemaversion is NULL)
  25973.     if @@error <> 0        
  25974.         begin
  25975.             RAISERROR(21305 , 16, -1)
  25976.             return (1)
  25977.         end
  25978.  
  25979.     /* only delete the publisher side check constraint at subscriber side */
  25980.     if @schematype=15 and 
  25981.         not exists (select * from sysmergepublications where  pubid=@pubid and LOWER(publisher)=LOWER(@@SERVERNAME)
  25982.             and publisher_db=db_name())
  25983.     begin
  25984.         select @objid=objid from sysmergearticles where artid=@artid and pubid=@pubid
  25985.         select @owner = user_name(uid) from sysobjects where id = @objid
  25986.         select @tablename = object_name(@objid)
  25987.         select @qualname = QUOTENAME(@owner) + '.' + QUOTENAME(@tablename)
  25988.         /*
  25989.         ** This is to removed CHECK constraint we accidentally propagated to subscriber side on identity check
  25990.         */
  25991.         select @constraintname = 'repl_identity_range_pub_' + convert(nvarchar(36), @artid)
  25992.         select @constraintname = REPLACE(@constraintname, '-', '_')
  25993.         if exists (select * from sysobjects where name = @constraintname and xtype='C')
  25994.         begin
  25995.             exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname)
  25996.             if @@ERROR<>0
  25997.                 return (1)
  25998.         end
  25999.  
  26000.         select @constraintname = 'repl_identity_range_repub_' + convert(nvarchar(36), @artid)
  26001.         select @constraintname = REPLACE(@constraintname, '-', '_')
  26002.         if exists (select * from sysobjects where name = @constraintname and xtype='C')
  26003.         begin
  26004.             exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname)
  26005.             if @@ERROR<>0
  26006.                 return (1)
  26007.         end
  26008.     end
  26009.     
  26010.     return (0)        
  26011. go
  26012. exec dbo.sp_MS_marksystemobject sp_MSinsertschemachange
  26013. go
  26014. grant exec on dbo.sp_MSinsertschemachange to public
  26015. go
  26016.  
  26017. raiserror('Creating procedure sp_MSgetviewcolumnlist', 0, 1)
  26018. GO
  26019.  
  26020. create procedure sp_MSgetviewcolumnlist(
  26021. @pubid                uniqueidentifier,
  26022. @source_objid        int,
  26023. @column_list         nvarchar(4000) OUTPUT
  26024. )
  26025. AS
  26026. /* 
  26027. ** if it is not vertically partitioned, then get all columns 
  26028. ** else get the column list as given in columns of sysmergearticles
  26029. */
  26030. declare @bitset        int
  26031. declare @columns    varbinary(125)
  26032. declare @setcolcnt    int
  26033. declare @colcnt        int
  26034. declare @colname    nvarchar(140)
  26035. declare @colid        int
  26036.  
  26037. select @columns = columns from sysmergearticles where objid = @source_objid and pubid=@pubid
  26038. select @column_list = ''
  26039. select @setcolcnt    = 0
  26040. select @colcnt = count(*) from syscolumns where id = @source_objid
  26041. declare collist CURSOR LOCAL FAST_FORWARD FOR 
  26042.        select name, colid from syscolumns where id = @source_objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid ASC
  26043. FOR READ ONLY
  26044. open collist
  26045. fetch collist into @colname, @colid
  26046. WHILE (@@fetch_status <> -1)
  26047. BEGIN
  26048.     set @bitset = 1
  26049.     if @columns is NOT NULL
  26050.         exec @bitset = sp_MStestbit @columns, @colid
  26051.     if @bitset<>0
  26052.     begin
  26053.         select @colname = QUOTENAME(@colname) --previously we use rowguidcol to replace 'rowguid'
  26054.         if @column_list=''                      --which can cause problems and is not necessary.
  26055.             select @column_list = @colname
  26056.         else
  26057.             select @column_list = @column_list + ', ' + @colname    
  26058.         select @setcolcnt = @setcolcnt + 1
  26059.     end                    
  26060. fetch next from collist into @colname, @colid            
  26061. END
  26062. close collist
  26063. deallocate collist
  26064. if @setcolcnt = @colcnt
  26065.     select @column_list = ' * '
  26066. return 0    
  26067. GO
  26068. exec dbo.sp_MS_marksystemobject sp_MSgetviewcolumnlist 
  26069. go
  26070. grant exec on dbo.sp_MSgetviewcolumnlist to public
  26071. go
  26072.  
  26073.  
  26074. raiserror('Creating procedure sp_MSvalidatearticle', 0, 1)
  26075. GO
  26076.  
  26077. create procedure sp_MSvalidatearticle
  26078.     @artid         uniqueidentifier,
  26079.     @pubid        uniqueidentifier,
  26080.     @expected_rowcount bigint = NULL OUTPUT,
  26081.     @expected_checksum numeric = NULL OUTPUT,
  26082.     @validation_type int = NULL,
  26083.     @full_or_fast tinyint = 2
  26084. as
  26085. -- get name of sync object and owner
  26086.     declare @objid int
  26087.     declare @syncobjid int
  26088.     declare @owner sysname
  26089.     declare @object sysname
  26090.     declare @view_type tinyint
  26091.     declare @temp_view tinyint
  26092.     declare @retcode int
  26093.     declare @rowcount_only int
  26094.     declare @source_objid int
  26095.     declare @column_list nvarchar(4000)
  26096.     /*
  26097.     ** Check to see if current publication has permission
  26098.     */
  26099.     if sessionproperty('replication_agent') = 0
  26100.     begin
  26101.         exec @retcode=sp_MSreplcheck_connection
  26102.             @pubid = @pubid
  26103.         if @retcode<>0 or @@ERROR<>0 return (1)
  26104.     end
  26105.     
  26106.     /* 
  26107.     The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns.
  26108.     In shiloh, the checksum functionality has changed.   So 7.0 subscribers will have the old checksum 
  26109.     routines, which generate different CRC values, and do not have functionality for vertical partitions,
  26110.     or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns).
  26111.  
  26112.     In 7.0, this was a bit column.  0 meant do not do just a rowcount - do a checksum.  1 meant just do a 
  26113.     rowcount.
  26114.  
  26115.     For Shiloh, this parameter is changed to a smallint with these options:
  26116.     0 - Do a 7.0 compatible checksum
  26117.     1 - Do a rowcount check only
  26118.     2 - Use new Shiloh checksum functionality.  Note that because 7.0 subscribers will 
  26119.     take this parameter as a bit type, not a smallint, it will be interpreted as simply
  26120.     ON.  That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0
  26121.     subscriber doing only rowcount validation.   The Shiloh subscribers will do both
  26122.     rowcount and checksum.  If you want 7.0 subscribers to do checksum validation, use 
  26123.     the value of 0 for this parameter.   Shiloh subscribers can do the 7.0 compatible 
  26124.     checksum, but that checksum has the same 7.0 limitations for vertical partitions 
  26125.     and differences in physical table structure.)
  26126.     */
  26127.     if @validation_type = 3
  26128.         set @rowcount_only  = 2
  26129.     else if @validation_type = 2
  26130.         set @rowcount_only  = 0
  26131.     else
  26132.         set @rowcount_only  = 1
  26133.  
  26134.               
  26135.     select @syncobjid = sync_objid, @objid = objid, @view_type = view_type from
  26136.         sysmergearticles where pubid = @pubid and artid = @artid
  26137.     select @source_objid = @objid        
  26138.     if (@syncobjid is not null and @syncobjid <> 0)
  26139.         set @objid = @syncobjid
  26140.         
  26141.     select @object = name, @owner = user_name(uid) from sysobjects where id = @objid
  26142.     
  26143. --  if sync object is a temp view, we can't do this...
  26144.     set @temp_view = 2
  26145.     if @view_type = @temp_view
  26146.         begin
  26147.         RAISERROR (20069, 16, -1)
  26148.         return 1
  26149.         end
  26150.     else if (@view_type = 1 and @rowcount_only = 0)
  26151.         begin
  26152.         RAISERROR (21017, 16, -1)
  26153.         return 1
  26154.         end
  26155.  
  26156.     exec @retcode = sp_MSgetviewcolumnlist @pubid, @source_objid, @column_list OUTPUT
  26157.     if @@ERROR<>0 OR @retcode <> 0
  26158.         return @retcode
  26159.  
  26160. --  call sp_table_validation
  26161.     exec @retcode = dbo.sp_table_validation @object, @expected_rowcount OUTPUT, @expected_checksum  OUTPUT, @rowcount_only, @owner, @full_or_fast, 0, NULL, @column_list
  26162.     if @@error<>0 return(1)
  26163.     return @retcode
  26164.     
  26165. GO
  26166. exec dbo.sp_MS_marksystemobject sp_MSvalidatearticle
  26167. go
  26168. grant exec on dbo.sp_MSvalidatearticle to public
  26169. go
  26170.  
  26171. raiserror('Creating procedure sp_MSsubscriptionvalidated', 0, 1)
  26172. GO
  26173.  
  26174. create procedure sp_MSsubscriptionvalidated
  26175.     @subid         uniqueidentifier,
  26176.     @pubid        uniqueidentifier,
  26177.     @log_attempt    bit = 0
  26178. as
  26179.     declare @now datetime
  26180.     declare @retcode int
  26181.  
  26182.     select @now=getdate()
  26183.     
  26184.     if sessionproperty('replication_agent') = 0
  26185.     begin
  26186.         exec @retcode=sp_MSreplcheck_connection
  26187.             @pubid = @pubid
  26188.         if @retcode<>0 or @@ERROR<>0 return (1)
  26189.     end
  26190.     
  26191.     if @log_attempt=0
  26192.         update sysmergesubscriptions set last_validated = @now, attempted_validate=@now
  26193.             where subid = @subid and pubid = @pubid
  26194.     else
  26195.         update sysmergesubscriptions set attempted_validate = @now
  26196.             where subid = @subid and pubid = @pubid        
  26197.     if @@rowcount <> 1 or @@error <> 0
  26198.         begin
  26199.         RAISERROR (20070, 16, -1)
  26200.         return (1)
  26201.         end
  26202.     return (0)
  26203. GO
  26204. exec dbo.sp_MS_marksystemobject sp_MSsubscriptionvalidated
  26205. go
  26206. grant exec on dbo.sp_MSsubscriptionvalidated to public
  26207.  
  26208. raiserror('Creating procedure sp_MSdroparticletombstones', 0, 1)
  26209. GO
  26210.  
  26211. create procedure sp_MSdroparticletombstones
  26212.     @artid         uniqueidentifier
  26213. as
  26214.     declare @tablenick int
  26215.     select @tablenick = nickname from sysmergearticles where artid = @artid
  26216.     if @tablenick is not null
  26217.     begin
  26218.         delete from dbo.MSmerge_tombstone where tablenick = @tablenick
  26219.         delete from dbo.MSmerge_contents where tablenick = @tablenick
  26220.         delete from dbo.MSmerge_genhistory where art_nick=@tablenick
  26221.     end
  26222.     return (0)
  26223. GO
  26224. exec dbo.sp_MS_marksystemobject sp_MSdroparticletombstones
  26225. go
  26226. grant exec on dbo.sp_MSdroparticletombstones to public
  26227.  
  26228. raiserror('Creating procedure sp_MSproxiedmetadata', 0, 1)
  26229. GO
  26230.  
  26231. create procedure sp_MSproxiedmetadata
  26232.     @tablenick    int,
  26233.     @rowguid    uniqueidentifier,
  26234.     @lineage    varbinary(256),
  26235.     @colv        varbinary(2048)
  26236. as
  26237.     declare @old_lin varbinary(256)
  26238.     declare @old_colv varbinary(2048)
  26239.     declare @retcode int
  26240.  
  26241. Loop:
  26242.     set @old_lin= NULL
  26243.     select @old_lin = lineage, @old_colv = colv1 from dbo.MSmerge_contents where
  26244.         tablenick = @tablenick and rowguid = @rowguid
  26245.  
  26246.     if (@old_lin IS NOT NULL)
  26247.     begin
  26248.         exec @retcode= master..xp_proxiedmetadata @lineage out, @colv out, @old_lin, @old_colv
  26249.         if @@error<>0 or @retcode<>0
  26250.         begin
  26251.             return(1)
  26252.         end
  26253.         update dbo.MSmerge_contents set lineage = @lineage, colv1 = @colv
  26254.             where tablenick = @tablenick and rowguid = @rowguid and lineage = @old_lin
  26255.         if @@rowcount = 0 goto Loop
  26256.     end
  26257.     else
  26258.     begin
  26259.         select @old_lin = lineage from dbo.MSmerge_tombstone where
  26260.             tablenick = @tablenick and rowguid = @rowguid
  26261.         if (@old_lin IS NULL)
  26262.             return (0)
  26263.  
  26264.         exec @retcode= master..xp_proxiedmetadata @lineage out, @colv out, @old_lin, NULL
  26265.         if @@error<>0 or @retcode<>0
  26266.         begin
  26267.             return(1)
  26268.         end
  26269.         update dbo.MSmerge_tombstone set lineage = @lineage
  26270.             where tablenick = @tablenick and rowguid = @rowguid and lineage = @old_lin
  26271.         if @@rowcount = 0 goto Loop
  26272.     end
  26273.  
  26274.     return (0)
  26275. GO
  26276. exec dbo.sp_MS_marksystemobject sp_MSproxiedmetadata
  26277. grant exec on dbo.sp_MSproxiedmetadata to public
  26278. go
  26279.  
  26280. raiserror('Creating procedure sp_MScontractsubsnb', 0,1)
  26281. GO
  26282.  
  26283. create PROCEDURE sp_MScontractsubsnb 
  26284.     (@pubid uniqueidentifier,
  26285.      @tablenick int,
  26286.      @basetable nvarchar(270))
  26287. AS
  26288.     declare        @filter_clause    nvarchar(4000)
  26289.     declare     @join_nick int
  26290.     declare        @jointable        nvarchar(270)
  26291.     declare     @filterid int
  26292.     declare     @retcode int
  26293.     declare     @tablenickstr nvarchar(10)
  26294.     set @tablenickstr = convert(nchar(10), @tablenick)
  26295.     
  26296.     /* First, try to remove rows from notbelong based on the article filter, if there is one */
  26297.     select @filter_clause = subset_filterclause from sysmergearticles where
  26298.         pubid = @pubid and nickname = @tablenick
  26299.     if len(@filter_clause) > 0
  26300.         begin
  26301.         exec ('delete from #notbelong with (paglock) where tablenick = ' + @tablenickstr + ' and rowguid in
  26302.                 (select RowGuidCol from ' + @basetable + ' where ' + @filter_clause + ')' )
  26303.         if @@error<>0 return(1)
  26304.         end
  26305.  
  26306.     /* Now loop over any join filters that have this as the base_table */
  26307.     select @filterid = min(join_filterid) from sysmergesubsetfilters
  26308.         where pubid = @pubid and art_nickname = @tablenick
  26309.     while @filterid is not null
  26310.         begin
  26311.         /* Get joining table and filter clause */
  26312.         select @join_nick = join_nickname, @filter_clause = join_filterclause
  26313.                 from sysmergesubsetfilters where pubid = @pubid and join_filterid = @filterid
  26314.         exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @jointable out, @pubid
  26315.         if @@error<>0 or @retcode<>0 return(1)
  26316.  
  26317.         /* Exec query to remove rows from #notbelong that still belong to partial */
  26318.         exec ('delete from #notbelong with (paglock) where tablenick = ' + @tablenickstr + ' and rowguid in
  26319.                 (select ' + @basetable + '.RowGuidCol from ' + @basetable + ', ' +
  26320.                 @jointable + ' where (' + @filter_clause + ') and ' + @jointable +
  26321.                 '.RowGuidCol not in (select rowguid from #notbelong))')
  26322.         if @@error<>0 return(1)
  26323.  
  26324.         /* Find the next filter that might apply */
  26325.         select @filterid = min(join_filterid) from sysmergesubsetfilters
  26326.             where pubid = @pubid and art_nickname = @tablenick and join_filterid > @filterid
  26327.         end
  26328.         return(0)
  26329. go
  26330.  
  26331. exec dbo.sp_MS_marksystemobject sp_MScontractsubsnb 
  26332. go
  26333. grant exec on dbo.sp_MScontractsubsnb to public
  26334. go
  26335.  
  26336. raiserror('Creating procedure sp_MSexpandsubsnb', 0,1)
  26337. GO
  26338.  
  26339. create PROCEDURE sp_MSexpandsubsnb (@pubid uniqueidentifier)
  26340. AS
  26341.     declare @filterid int
  26342.     declare @base_nick int
  26343.     declare @join_nick int
  26344.     declare @basetable nvarchar(270)
  26345.     declare @jointable nvarchar(270)
  26346.     declare @join_clause nvarchar(4000)
  26347.     declare @retcode int
  26348.     declare @error int
  26349.     declare @rowcount int
  26350.     declare @base_nickstr nvarchar(10)
  26351.     declare @join_unique_key int
  26352.  
  26353.     /* get first filter to expand on */
  26354.     select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
  26355.         where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag
  26356.  
  26357.     while @filterid is not null
  26358.         begin
  26359.         /* get join clause and tables for this filter */
  26360.         select @join_nick = join_nickname, @join_clause = join_filterclause,
  26361.             @base_nick = art_nickname, @join_unique_key = join_unique_key from sysmergesubsetfilters where
  26362.                 pubid = @pubid and join_filterid = @filterid
  26363.         exec @retcode = dbo.sp_MStablenamefromnick @join_nick, @jointable out, @pubid
  26364.         if @@error<>0 or @retcode<>0 return(1)
  26365.         exec @retcode = dbo.sp_MStablenamefromnick @base_nick, @basetable out, @pubid
  26366.         if @@error<>0 or @retcode<>0 return(1)
  26367.         set @base_nickstr = convert(nchar(10), @base_nick)
  26368.  
  26369.         /* Mark rows so that we know we've expanded those rows for this filter */
  26370.         update #notbelong set flag = @filterid where flag < @filterid
  26371.         
  26372.         /* exec an insert/select query to expand #notbelong */
  26373.         exec ('insert into #notbelong (tablenick, rowguid, flag) select distinct ' +
  26374.                 @base_nickstr + ', ' + @basetable + '.RowGuidCol, 0 from ' + @basetable + 
  26375.                 ', ' + @jointable + ' where ( ' + @jointable + '.RowGuidCol in 
  26376.                     (select rowguid from #notbelong) ) and (' + @join_clause + ')')
  26377.         select @error=@@error, @rowcount=@@rowcount
  26378.         if @error<>0 return(1)
  26379.         /* 
  26380.         ** if any rows inserted, try to contract the #notbelong table.
  26381.         ** Only join filters that are non unique need to contract the 
  26382.         ** NOTBELONGS table - 
  26383.         */
  26384.         if @rowcount <> 0 and @join_unique_key = 0
  26385.         begin
  26386.             exec @retcode = dbo.sp_MScontractsubsnb @pubid, @base_nick, @basetable
  26387.             if @@error<>0 or @retcode<>0 return(1)
  26388.         end
  26389.         
  26390.         /* get next filter to expand with */
  26391.         select @filterid = min(join_filterid) from sysmergesubsetfilters f, #notbelong nb
  26392.             where pubid = @pubid and nb.tablenick = f.join_nickname and f.join_filterid > nb.flag
  26393.         end
  26394.  
  26395.         return(0)
  26396. go
  26397.  
  26398. exec dbo.sp_MS_marksystemobject sp_MSexpandsubsnb 
  26399. go
  26400. grant exec on dbo.sp_MSexpandsubsnb to public
  26401. go
  26402. raiserror('Creating procedure sp_MSdelsubrows', 0,1)
  26403. GO
  26404.  
  26405. create PROCEDURE sp_MSdelsubrows 
  26406.     (@rowguid         uniqueidentifier,
  26407.     @tablenick     int,
  26408.     @metadata_type tinyint, /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred, 6 - system delete */
  26409.     @lineage_old varbinary(255),
  26410.     @generation int,
  26411.     @lineage_new varbinary(255),
  26412.     @pubid uniqueidentifier = NULL,
  26413.     @rowsdeleted INT = NULL OUTPUT)
  26414.  
  26415. as
  26416.     declare @match             int
  26417.     declare @errcode        int
  26418.     declare @new_metatype    tinyint
  26419.     declare @retcode         smallint
  26420.     declare @reason         nvarchar(255)
  26421.     declare @procname         sysname
  26422.     declare @tnstr            nvarchar(11)
  26423.     declare @error int, @rowcount int
  26424.     
  26425.     /* By default this sp should delete exactly one row */
  26426.     set    @rowsdeleted = 1
  26427.     
  26428.     /*
  26429.     ** Check to see if current publication has permission
  26430.     */
  26431.     if sessionproperty('replication_agent') = 0
  26432.     begin
  26433.         exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  26434.         if @retcode<>0 or @@ERROR<>0 return (0)
  26435.     end
  26436.         
  26437.     /* Parameter validation */
  26438.     if (@rowguid is null)
  26439.     begin
  26440.         RAISERROR(14043, 16, -1, '@rowguid')
  26441.         return (0)
  26442.     end
  26443.     if (@tablenick is null)
  26444.     begin
  26445.         RAISERROR(14043, 16, -1, '@tablenick')
  26446.         return (0)
  26447.     end
  26448.     if (@lineage_new is null)
  26449.     begin
  26450.         RAISERROR(14043, 16, -1, '@lineage_new')
  26451.         return (0)
  26452.     end
  26453.  
  26454.     -- Are we just changing the type of a tombstone?
  26455.     if (@metadata_type = 5 or @metadata_type = 1)
  26456.     begin
  26457.         if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  26458.         begin
  26459.             
  26460.             if (@metadata_type = 5)
  26461.                 set @reason = formatmessage (20563) -- Remove from partial
  26462.             else if (@metadata_type = 1)
  26463.                 set @reason = formatmessage (20562) -- User delete
  26464.  
  26465.             update dbo.MSmerge_tombstone 
  26466.                 set type = @metadata_type, reason = @reason, generation = @generation, lineage = @lineage_new 
  26467.                 where rowguid = @rowguid and tablenick = @tablenick
  26468.         return 1
  26469.         end
  26470.     end
  26471.     
  26472.     -- Are we just changing the type of a tombstone?
  26473.     else if (@metadata_type = 6)
  26474.     begin
  26475.         if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  26476.         begin
  26477.             set @reason = formatmessage (20564) -- System deleted
  26478.             update dbo.MSmerge_tombstone set type = @metadata_type, reason = @reason 
  26479.                 where rowguid = @rowguid and tablenick = @tablenick
  26480.             return 1
  26481.         end
  26482.     end
  26483.  
  26484.     -- begin transaction and lock row that we plan to delete
  26485.     begin transaction
  26486.     save tran sp_MSdelsubrows
  26487.  
  26488.     select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid = @pubid
  26489.     exec @retcode = @procname @type =8, @rowguid=@rowguid
  26490.     IF @@ERROR<>0 or @retcode<>0
  26491.     begin
  26492.         set @errcode= 0
  26493.         goto Failure
  26494.     end
  26495.         
  26496.     if @metadata_type = 5
  26497.     begin
  26498.         set @match = 1
  26499.         set @new_metatype = 5
  26500.     end
  26501.     else if @metadata_type = 6
  26502.     begin
  26503.         set @match = 1
  26504.         set @new_metatype = 6
  26505.     end
  26506.     else if @metadata_type = 7
  26507.     begin
  26508.         set @match = 1
  26509.         set @new_metatype = 7
  26510.     end
  26511.     else
  26512.     begin
  26513.         exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
  26514.         IF @@ERROR<>0 or @retcode<>0
  26515.         begin
  26516.             set @errcode= 0
  26517.             goto Failure
  26518.         end
  26519.  
  26520.         set @new_metatype = 1
  26521.     end
  26522.  
  26523.     if (@match = 1)
  26524.     begin
  26525.         
  26526.         /* If there are any joinfilters with this as the join table, try to expand to deleting
  26527.         ** a set of related rows.
  26528.         */
  26529.         if (exists (select * from sysmergesubsetfilters where pubid = @pubid and join_nickname = @tablenick))
  26530.         begin
  26531.             declare @tn int
  26532.             declare @table_name nvarchar(270)
  26533.             
  26534.             select @rowsdeleted = 0
  26535.  
  26536.             set @reason = formatmessage (20563) -- Moved out of partial range
  26537.             /* create temp and put in our tablenick, rowguid */
  26538.             create table #notbelong (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL)
  26539.             create index #indnbelong on #notbelong (tablenick, rowguid)
  26540.             insert into #notbelong (tablenick, rowguid, flag) values
  26541.                     (@tablenick, @rowguid, 0)
  26542.             
  26543.             /* call expand proc */
  26544.             exec @retcode = dbo.sp_MSexpandsubsnb @pubid
  26545.             IF @@ERROR<>0 or @retcode<>0
  26546.             begin
  26547.                 set @errcode= 0
  26548.                 goto Failure
  26549.             end
  26550.         
  26551.             select @tn = max(tablenick) from #notbelong where flag > -1
  26552.             while @tn is not null
  26553.             begin
  26554.                 select @tnstr = convert(nvarchar(11), @tn)
  26555.  
  26556.                 exec @retcode = dbo.sp_MStablenamefromnick @tn, @table_name out, @pubid
  26557.                 -- delete all rows indicated by the temp table
  26558.                 IF @@ERROR<>0 or @retcode<>0
  26559.                 begin
  26560.                     set @errcode= 0
  26561.                     goto Failure
  26562.                 end
  26563.                 exec ('delete from ' + @table_name + ' where RowGuidCol in 
  26564.                     (select rowguid from #notbelong where tablenick = ' + @tnstr + ')' )
  26565.                 select @error=@@error, @rowcount=@@rowcount
  26566.                 IF @error<>0
  26567.                 begin
  26568.                     set @errcode= 0
  26569.                     goto Failure
  26570.                 end
  26571.  
  26572.                 select @rowsdeleted = @rowsdeleted + @rowcount
  26573.             
  26574.                 -- move on to next nickname - decreasing makes delete order correct
  26575.                 update #notbelong set flag = -1 where tablenick = @tn
  26576.                 select @tn = max(tablenick) from #notbelong where flag > -1
  26577.             end
  26578.  
  26579.             -- change tombstone type for those rows
  26580.             update dbo.MSmerge_tombstone 
  26581.             set type = 5, reason = @reason 
  26582.             from #notbelong nb, dbo.MSmerge_tombstone ts
  26583.             where ts.tablenick = nb.tablenick and
  26584.             ts.rowguid = nb.rowguid
  26585.  
  26586.             drop table #notbelong
  26587.             exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  26588.             IF @@ERROR<>0 or @retcode<>0
  26589.             begin
  26590.                 set @errcode= 0
  26591.                 goto Failure
  26592.             end
  26593.         end
  26594.         else
  26595.         begin
  26596.             
  26597.             -- select_proc makes a delete with @type = 5, despite its name. 
  26598.             exec @retcode = @procname @type =5, @rowguid=@rowguid
  26599.             select @error= @@error, @rowcount= @@rowcount
  26600.             IF @error<>0 or @retcode<>0
  26601.             begin
  26602.                 set @errcode= 0
  26603.                 goto Failure
  26604.             end
  26605.         
  26606.             if (@rowcount = 1)
  26607.             begin
  26608.                 exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  26609.                 IF @@ERROR<>0 or @retcode<>0
  26610.                 begin
  26611.                     set @errcode= 0
  26612.                     goto Failure
  26613.                 end
  26614.             end
  26615.             else
  26616.                 goto Failure
  26617.         end
  26618.     end
  26619.     else
  26620.     begin
  26621.         set @errcode= 2
  26622.         goto Failure
  26623.     end
  26624.  
  26625.     commit tran
  26626.     return 1 -- in sp_MSdelsubrows, 1=okay
  26627.  
  26628. Failure:
  26629.     rollback tran sp_MSdelsubrows
  26630.     commit tran
  26631.     return(@errcode) -- in sp_MSdelsubrows, 0=error
  26632.  
  26633. go
  26634. exec dbo.sp_MS_marksystemobject sp_MSdelsubrows 
  26635. go
  26636. grant exec on dbo.sp_MSdelsubrows to public
  26637. go
  26638.  
  26639. raiserror('Creating procedure sp_MSdelsubrowsbatch', 0,1)
  26640. GO
  26641. create PROCEDURE sp_MSdelsubrowsbatch 
  26642.     (@tablenick int,
  26643.      @rowguid_array varbinary(8000),
  26644.      @metadatatype_array varbinary(500), /* 0 - Missing, 1 - Tombstone, 2 - Contents, 3 - ContentsDeferred, 6 - system delete */
  26645.      @oldlineage_len_array varbinary(1000),        -- -- specifies the number of lineages in the @oldlineage_array.
  26646.      @oldlineage_array image,
  26647.      @generation_array varbinary(2000),
  26648.      @newlineage_len_array varbinary(1000),        -- specifies the number of lineages in the @newlineage_array.
  26649.      @newlineage_array image,
  26650.      @pubid uniqueidentifier = NULL,
  26651.      @rowsdeleted INT = NULL OUTPUT)
  26652.  
  26653. as
  26654.     declare @rowguid uniqueidentifier, @metadata_type tinyint, @lineage_old varbinary(255),    
  26655.             @generation int, @lineage_new varbinary(255), @match int, @errcode int, @new_metatype tinyint, 
  26656.             @retcode smallint, @reason nvarchar(255), @procname sysname, @tnstr nvarchar(11), @error int, @rowcount int,
  26657.             @tablenicklast int, @rowguidarraylen int, @oldlineage_len smallint, @newlineage_len smallint,
  26658.             @guidoffset int, @metatypeoffset int, @oldlinlenoffset int, @newlinlenoffset int, @oldlinoffset int,
  26659.             @newlinoffset int, @genoffset int, @transaction_started bit
  26660.             
  26661.     declare @rowstochangetype TABLE (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL)
  26662.  
  26663.     -- Do all DDL first
  26664.     create table #notbelong (    tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL, generation int NULL, 
  26665.                                 lineage_old varbinary(255) NULL, metadatatype_old tinyint NULL, 
  26666.                                 lineage_new varbinary(255) NULL, metadatatype_new tinyint NULL, original_row bit NULL default 0)
  26667.     create index #indnbelong on #notbelong (tablenick, rowguid)
  26668.                 
  26669.     /*
  26670.     ** Check to see if current publication has permission. Skip check if caller is the merge agent.
  26671.     */
  26672.     if sessionproperty('replication_agent') = 0
  26673.     begin
  26674.         exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  26675.         if @retcode<>0 or @@ERROR<>0 return (0)
  26676.     end
  26677.         
  26678.     /* Parameter validation */
  26679.     if (@rowguid_array is null)
  26680.     begin
  26681.         RAISERROR(14043, 16, -1, '@rowguid_array')
  26682.         return (0)
  26683.     end
  26684.     if (@tablenick is null)
  26685.     begin
  26686.         RAISERROR(14043, 16, -1, '@tablenick_array')
  26687.         return (0)
  26688.     end
  26689.     if (@newlineage_array is null)
  26690.     begin
  26691.         RAISERROR(14043, 16, -1, '@newlineage_array')
  26692.         return (0)
  26693.     end
  26694.  
  26695.     set    @rowsdeleted = 0
  26696.     set @transaction_started = 0
  26697.  
  26698.     -- initialize offsets and length for walking through arrays
  26699.     set @guidoffset = 1
  26700.     set @metatypeoffset = 1
  26701.     set @oldlinlenoffset = 1
  26702.     set @newlinlenoffset = 1
  26703.     set @oldlinoffset = 1
  26704.     set @newlinoffset = 1
  26705.     set @genoffset = 1
  26706.     
  26707.     set @rowguidarraylen = datalength(@rowguid_array)
  26708.  
  26709.     -- walk through arrays and populate temp table
  26710.     while (@guidoffset < @rowguidarraylen)
  26711.     begin
  26712.         set @rowguid = substring(@rowguid_array, @guidoffset, 16)    -- 16 = sizeof uniqueidentifier (rowguid)
  26713.         set @metadata_type = substring(@metadatatype_array, @metatypeoffset, 1)    -- 1 = sizeof tinyint (metadata_type)
  26714.         set @generation = substring(@generation_array, @genoffset, 4) -- 4 = sizeof int (generation)
  26715.         set @oldlineage_len = substring(@oldlineage_len_array, @oldlinlenoffset, 2) -- 2 = sizeof smallint (oldlineage_len)
  26716.         set @newlineage_len = substring(@newlineage_len_array, @newlinlenoffset, 2) -- 2 = sizeof smallint (newlineage_len)
  26717.         set @lineage_old = substring(@oldlineage_array, @oldlinoffset, @oldlineage_len) -- @oldlineage_len = sizeof old lineage for current row
  26718.         set @lineage_new = substring(@newlineage_array, @newlinoffset, @newlineage_len) -- @newlineage_len = sizeof new lineage for current row
  26719.  
  26720.         -- increment offsets for next row
  26721.         set @guidoffset = @guidoffset + 16
  26722.         set @metatypeoffset = @metatypeoffset + 1
  26723.         set @genoffset = @genoffset + 4
  26724.         set @oldlinlenoffset = @oldlinlenoffset + 2
  26725.         set @newlinlenoffset = @newlinlenoffset + 2
  26726.         set @oldlinoffset = @oldlinoffset + @oldlineage_len
  26727.         set @newlinoffset = @newlinoffset + @newlineage_len
  26728.  
  26729.         -- Insert the old metadata type as the new metadata type. We can modify later if it is supposed to be different.
  26730.         insert into #notbelong (tablenick, rowguid, flag, generation, lineage_old, metadatatype_old, lineage_new, metadatatype_new, original_row) values (@tablenick, @rowguid, 0, @generation, @lineage_old, @metadata_type, @lineage_new, @metadata_type, 1)
  26731.     end
  26732.     
  26733.     if (exists(select * from #notbelong))
  26734.     begin
  26735.         declare @tn int
  26736.         declare @table_name nvarchar(270)
  26737.                     
  26738.         -- Expansion is an expensive and time-consuming process. Defer starting transaction until after expansion 
  26739.         -- has taken place.
  26740.  
  26741.         /* call expand proc */
  26742.         exec @retcode = dbo.sp_MSexpandsubsnb @pubid
  26743.         IF @@ERROR<>0 or @retcode<>0
  26744.         begin
  26745.             set @errcode= 0
  26746.             goto Failure
  26747.         end
  26748.  
  26749.         select @procname = select_proc from sysmergearticles where nickname = @tablenick and pubid = @pubid
  26750.  
  26751.         -- After the #notbelong has been expanded, the original_row column can be used to distinguish original rows
  26752.         -- from the rows that were brought in by the expansion.
  26753.  
  26754.         -- open a cursor on #notbelong for rows with original_row = 1
  26755.         declare original_rows_1 CURSOR LOCAL FAST_FORWARD for 
  26756.         select rowguid, generation, lineage_old, metadatatype_old, lineage_new from #notbelong where tablenick = @tablenick and original_row = 1
  26757.         FOR READ ONLY
  26758.         open original_rows_1
  26759.         fetch original_rows_1 into @rowguid, @generation, @lineage_old, @metadata_type, @lineage_new
  26760.  
  26761.         begin transaction
  26762.         save tran start_of_batch
  26763.         set @transaction_started = 1
  26764.  
  26765.         while (@@fetch_status <> -1)
  26766.         begin
  26767.             
  26768.             -- Are we just changing the type of a tombstone?
  26769.             if (@metadata_type = 5 or @metadata_type = 1)
  26770.             begin
  26771.                 if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  26772.                 begin
  26773.                     if (@metadata_type = 5)
  26774.                         set @reason = formatmessage (20563) -- Remove from partial
  26775.                     else if (@metadata_type = 1)
  26776.                         set @reason = formatmessage (20562) -- User delete
  26777.  
  26778.                     update dbo.MSmerge_tombstone 
  26779.                         set type = @metadata_type, reason = @reason, generation = @generation, lineage = @lineage_new 
  26780.                         where rowguid = @rowguid and tablenick = @tablenick
  26781.  
  26782.     
  26783.                     -- This row will later be removed from #notbelong. We were only supposed to update the tombstone
  26784.                     -- metadata type for this row (which we have already done above).
  26785.                     insert into @rowstochangetype values (@tablenick, @rowguid)
  26786.                     fetch original_rows_1 into @rowguid, @generation, @lineage_old, @metadata_type, @lineage_new
  26787.                     continue    -- on to the next row
  26788.                 end
  26789.             end
  26790.         
  26791.             -- Are we just changing the type of a tombstone?
  26792.             else if (@metadata_type = 6)
  26793.             begin
  26794.                 if exists (select * from dbo.MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)
  26795.                 begin
  26796.                     set @reason = formatmessage (20564) -- System deleted
  26797.                     update dbo.MSmerge_tombstone set type = @metadata_type, reason = @reason 
  26798.                         where rowguid = @rowguid and tablenick = @tablenick
  26799.  
  26800.     
  26801.                     -- This row will later be removed from #notbelong. We were only supposed to update the tombstone
  26802.                     -- metadata type for this row (which we have already done above).
  26803.                     insert into @rowstochangetype values (@tablenick, @rowguid)
  26804.                     fetch original_rows_1 into @rowguid, @generation, @lineage_old, @metadata_type, @lineage_new
  26805.                     continue    -- on to the next row
  26806.                 end
  26807.             end
  26808.  
  26809.             -- lock this particular row of the base table
  26810.             exec @retcode = @procname @type = 8, @rowguid=@rowguid
  26811.             IF @@ERROR<>0 or @retcode<>0
  26812.             begin
  26813.                 set @errcode= 0
  26814.                 close original_rows_1
  26815.                 deallocate original_rows_1
  26816.                 goto Failure
  26817.             end
  26818.             
  26819.             if @metadata_type = 5
  26820.             begin
  26821.                 set @match = 1
  26822.                 set @new_metatype = 5
  26823.             end
  26824.             else if @metadata_type = 6
  26825.             begin
  26826.                 set @match = 1
  26827.                 set @new_metatype = 6
  26828.             end
  26829.             else if @metadata_type = 7
  26830.             begin
  26831.                 set @match = 1
  26832.                 set @new_metatype = 7
  26833.             end
  26834.             else
  26835.             begin
  26836.                 exec @retcode=sp_MScheckmetadatamatch @metadata_type, @rowguid, @tablenick, @lineage_old, @match output
  26837.                 IF @@ERROR<>0 or @retcode<>0
  26838.                 begin
  26839.                     set @errcode= 0
  26840.                     close original_rows_1
  26841.                     deallocate original_rows_1
  26842.                     goto Failure
  26843.                 end
  26844.  
  26845.                 set @new_metatype = 1
  26846.             end
  26847.  
  26848.             if (@match = 1)
  26849.             begin
  26850.                 if (@metadata_type <> @new_metatype)
  26851.                 begin
  26852.                     -- we will later need this new metadata type when calling sp_MSsetrowmetadata
  26853.                     update #notbelong set metadatatype_new = @new_metatype where tablenick = @tablenick and rowguid = @rowguid and original_row = 1
  26854.                 end
  26855.             end
  26856.             else
  26857.             begin
  26858.                 set @errcode= 2
  26859.                 close original_rows_1
  26860.                 deallocate original_rows_1
  26861.                 goto Failure
  26862.             end
  26863.  
  26864.             fetch original_rows_1 into @rowguid, @generation, @lineage_old, @metadata_type, @lineage_new
  26865.  
  26866.         end
  26867.  
  26868.         close original_rows_1
  26869.         deallocate original_rows_1
  26870.  
  26871.         -- delete the rows in #notbelong that needn't be deleted. We were only supposed to update the tombstone
  26872.         -- metadata type for those rows (which we have already done above).
  26873.         delete #notbelong with (paglock) from #notbelong a, @rowstochangetype b where a.tablenick = b.tablenick and a.rowguid = b.rowguid
  26874.         
  26875.         select @tn = max(tablenick) from #notbelong where flag > -1
  26876.         while @tn is not null
  26877.         begin
  26878.             select @tnstr = convert(nvarchar(11), @tn)
  26879.             exec @retcode = dbo.sp_MStablenamefromnick @tn, @table_name out, @pubid
  26880.             -- delete all rows indicated by the temp table
  26881.             IF @@ERROR<>0 or @retcode<>0
  26882.             begin
  26883.                 set @errcode= 0
  26884.                 goto Failure
  26885.             end
  26886.             exec ('delete from ' + @table_name + ' where RowGuidCol in 
  26887.                 (select rowguid from #notbelong where tablenick = ' + @tnstr + ')' )
  26888.             select @error=@@error, @rowcount=@@rowcount
  26889.             IF @error<>0
  26890.             begin
  26891.                 set @errcode= 0
  26892.                 goto Failure
  26893.             end
  26894.  
  26895.             select @rowsdeleted = @rowsdeleted + @rowcount
  26896.                 
  26897.             -- move on to next nickname - decreasing makes delete order correct
  26898.             update #notbelong set flag = -1 where tablenick = @tn
  26899.             select @tn = max(tablenick) from #notbelong where flag > -1
  26900.         end
  26901.  
  26902.         set @reason = formatmessage (20563) -- Moved out of partial range
  26903.  
  26904.         -- change tombstone type for the non-original rows (the rows that got deleted via expansion).
  26905.         update dbo.MSmerge_tombstone 
  26906.         set type = 5, reason = @reason 
  26907.         from #notbelong nb, dbo.MSmerge_tombstone ts
  26908.         where ts.tablenick = nb.tablenick and
  26909.         ts.rowguid = nb.rowguid
  26910.         and nb.original_row <> 1
  26911.  
  26912.         -- open a cursor and get the new metadata types for the original rows and then call sp_MSsetrowmetadata for each original row.
  26913.         declare original_rows_2 CURSOR LOCAL FAST_FORWARD for 
  26914.         select tablenick, rowguid, generation, lineage_new, metadatatype_new from #notbelong where original_row = 1
  26915.         FOR READ ONLY
  26916.         open original_rows_2
  26917.         fetch original_rows_2 into @tablenick, @rowguid, @generation, @lineage_new, @new_metatype
  26918.         while (@@fetch_status <> -1)
  26919.         begin
  26920.             -- Call sp_MSsetrowmetadata for only the original rows whose delete requests were passed in to this proc.
  26921.             exec @retcode= dbo.sp_MSsetrowmetadata @tablenick, @rowguid, @generation, @lineage_new, NULL, @new_metatype
  26922.             IF @@ERROR<>0 or @retcode<>0
  26923.             begin
  26924.                 set @errcode= 0
  26925.                 close original_rows_2
  26926.                 deallocate original_rows_2
  26927.                 goto Failure
  26928.             end
  26929.             fetch original_rows_2 into @tablenick, @rowguid, @generation, @lineage_new, @new_metatype
  26930.         end
  26931.         close original_rows_2
  26932.         deallocate original_rows_2
  26933.  
  26934.         commit tran
  26935.  
  26936.     end
  26937.  
  26938.  
  26939.     drop table #notbelong
  26940.     return 1 -- in sp_MSdelsubrows, 1=okay
  26941.  
  26942. Failure:
  26943.  
  26944.     -- instead of checking @@trancount, check our bit flag. This is safer as we can rely on it whether or not we are called 
  26945.     -- from an outer transaction.
  26946.     if (@transaction_started = 1)
  26947.     begin
  26948.         rollback tran start_of_batch
  26949.         commit tran
  26950.     end
  26951.  
  26952.  
  26953.     drop table #notbelong
  26954.  
  26955.     if @errcode = 1
  26956.         set @errcode = 0
  26957.  
  26958.     return(@errcode) -- in sp_MSdelsubrows, 0=error
  26959.  
  26960. go
  26961. exec dbo.sp_MS_marksystemobject sp_MSdelsubrowsbatch 
  26962. go
  26963. grant exec on dbo.sp_MSdelsubrowsbatch to public
  26964. go
  26965.  
  26966. raiserror('Creating procedure sp_MSscriptviewproc', 0,1)
  26967. go
  26968. create procedure dbo.sp_MSscriptviewproc (
  26969.     @viewname  sysname,
  26970.     @ownername sysname,
  26971.     @procname  nvarchar(290),
  26972.     @rgcol     sysname,
  26973.     @objid     int = NULL -- for possible backward comp. issue
  26974.     )
  26975. as
  26976. begin
  26977.  
  26978.     declare @retcode        smallint
  26979.     declare @colname        nvarchar(258)
  26980.     declare @view_id        int
  26981.     declare @iscomputed     tinyint
  26982.     declare @xtype          sysname
  26983.     select @retcode=0
  26984.     declare @proctext       table (line_no int primary key identity(1,1), line nvarchar(4000))
  26985.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  26986.  
  26987.     set nocount on
  26988.     select @procname=QUOTENAME(@procname)
  26989.     insert into @proctext (line) values (
  26990. 'create procedure dbo.' + @procname + ' (@tablenick int, @max_rows int = NULL,
  26991.     @guidlast uniqueidentifier = ''00000000-0000-0000-0000-000000000000'') 
  26992.     AS
  26993.  
  26994.     set nocount on
  26995.     set rowcount 0
  26996.     if  @max_rows is not null
  26997.     begin
  26998.         -- used to select data for initial pop. of subscriber for dynamic filtered publication
  26999.         set rowcount @max_rows
  27000.         declare @lin varbinary (255)
  27001.         declare @cv varbinary (2048)
  27002.         declare @replnick int
  27003.         declare @objid int
  27004.         declare @ccols int
  27005.  
  27006.         select @objid = objid from sysmergearticles where nickname = @tablenick
  27007.         select @ccols = max(colid) from syscolumns where id = @objid
  27008.         
  27009.         exec dbo.sp_MSgetreplnick @nickname = @replnick out
  27010.         if (@@error <> 0) or @replnick IS NULL 
  27011.         begin
  27012.             RAISERROR (14055, 11, -1)
  27013.             RETURN(1)
  27014.         end                 
  27015.         set @lin = { fn UPDATELINEAGE(0x0, @replnick, 1) }
  27016.         set @cv = { fn INITCOLVS(@ccols, @replnick) }
  27017.  
  27018.         select @tablenick, v.' + @rgcol + ', coalesce (c.generation,1), 
  27019.             coalesce (c.lineage, @lin), coalesce (c.colv1, @cv)')
  27020.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27021.  
  27022.     if @objid is not NULL and exists (select * from syscolumns where id = @objid 
  27023.         and (iscomputed=1 or type_name(xtype)='timestamp'))
  27024.     begin
  27025.         select @view_id = object_id(@viewname)
  27026.         declare collist cursor local fast_forward for 
  27027.             select name from syscolumns where id = @view_id order by colid asc
  27028.                 for read only
  27029.         open collist
  27030.         fetch collist into @colname
  27031.         while (@@fetch_status <> -1)
  27032.         begin
  27033.             --since a view does not preserve computed/timestamp property, we have to rely on the base table
  27034.             select @iscomputed=iscomputed, @xtype=xtype from syscolumns where id = @objid and name=@colname
  27035.             if @iscomputed=0 and type_name(@xtype) <> 'timestamp'
  27036.             begin
  27037.                 select @colname = QUOTENAME(@colname) --previously we use rowguidcol to replace 'rowguid'
  27038.                                                       --which can cause problems and is not necessary.
  27039.                 insert @proctext (line) values('
  27040.             , v.' + @colname) 
  27041.                 if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27042.             end
  27043.             fetch next from collist into @colname
  27044.         end                 
  27045.     end
  27046.     else
  27047.     begin
  27048.         insert into @proctext (line) values (
  27049. '             , v.*')
  27050.         if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27051.     end
  27052.  
  27053.     insert into @proctext (line) values ('
  27054.             from ' +
  27055.                  QUOTENAME(@ownername) + '.' +
  27056.                     QUOTENAME(@viewname) + ' v left outer join  dbo.MSmerge_contents c on
  27057.                       v.' + @rgcol + ' = c.rowguid  and c.tablenick = @tablenick where v.' + @rgcol + ' > @guidlast 
  27058.                      order by v.' + @rgcol + '
  27059.         return (1)      
  27060.     end
  27061.  
  27062.     insert into #belong (tablenick, rowguid, flag, skipexpand, partchangegen, joinchangegen)
  27063.         select ct.tablenick, ct.rowguid, 0, 0, ct.partchangegen, ct.joinchangegen
  27064.                     from  #contents_subset ct, ' + QUOTENAME(@ownername) + '.' +
  27065.                     QUOTENAME(@viewname) + ' v where ct.tablenick = @tablenick
  27066.                     and ct.rowguid = v.' + @rgcol + '  
  27067.     if @@ERROR <> 0
  27068.         begin
  27069.         RAISERROR(''Error selecting from view'' , 16, -1)
  27070.         return (1)  
  27071.         end')
  27072.             
  27073.     select line from @proctext order by line_no asc
  27074. Failure:
  27075.     return @retcode
  27076. end
  27077. go
  27078. exec dbo.sp_MS_marksystemobject sp_MSscriptviewproc
  27079. grant execute on sp_MSscriptviewproc to public
  27080.  
  27081. raiserror('Creating procedure sp_MSmakeviewproc', 0,1)
  27082. GO
  27083.  
  27084. create procedure sp_MSmakeviewproc (
  27085.     @viewname sysname,
  27086.     @ownername sysname,
  27087.     @procname nvarchar(290),
  27088.     @rgcol sysname,
  27089.     @objid int = NULL --for possible backward comp. issue
  27090.     )
  27091. as
  27092. begin
  27093.     declare @retcode        smallint
  27094.     declare @command        nvarchar(4000)
  27095.     declare @db_name        sysname
  27096.     set nocount on
  27097.  
  27098.     select @retcode = 0
  27099.     select @db_name = db_name()
  27100.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27101.  
  27102.     select @command = N'exec dbo.sp_MSscriptviewproc 
  27103.         @viewname = ' + fn_replmakestringliteral(@viewname) collate database_default + '
  27104.         ,@ownername = ' + fn_replmakestringliteral(@ownername) collate database_default + '
  27105.         ,@procname = ' + fn_replmakestringliteral(@procname) collate database_default + '
  27106.         ,@rgcol = ' + fn_replmakestringliteral(@rgcol) collate database_default + '
  27107.         ,@objid = ' + isnull(convert(nvarchar(20), @objid), N'null') 
  27108.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27109.  
  27110.     exec @retcode = master.dbo.xp_execresultset @command, @db_name
  27111.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27112.  
  27113.     select @procname=QUOTENAME(@procname)
  27114.     exec dbo.sp_MS_marksystemobject @procname
  27115.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27116.     exec ('grant exec on ' + @procname + ' to public')
  27117.     if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Failure end 
  27118.  
  27119. Failure:
  27120.     return @retcode
  27121. end
  27122. go
  27123. exec dbo.sp_MS_marksystemobject sp_MSmakeviewproc 
  27124. go
  27125. create procedure sp_MScreatebeforetable
  27126.     @objid int
  27127. AS
  27128.     declare     @command            nvarchar(4000)
  27129.     declare     @objidstr            nvarchar(12)
  27130.     declare     @dbname             sysname
  27131.     declare        @oldname            sysname
  27132.     declare     @newname             sysname
  27133.     declare     @nameguid             uniqueidentifier
  27134.     declare     @before_rowguidname sysname
  27135.     declare     @retcode             int
  27136.      declare     @tablenick                 int
  27137.     set nocount on
  27138.  
  27139.     set @before_rowguidname = NULL
  27140.  
  27141. -- If no publication including this table needs before images, just return
  27142.     if not exists (select * from sysmergepublications p, sysmergearticles a where
  27143.             a.objid = @objid and p.pubid = a.pubid and p.keep_before_values = 1)
  27144.         return (0)
  27145.     select @tablenick = max(nickname) from sysmergearticles where objid = @objid
  27146.     if @tablenick is null return (1)
  27147.  
  27148. -- If a before image table already exists for this table, we need to drop it and create a new one
  27149.     select @oldname = max(o.name) from sysobjects o, sysmergearticles a where
  27150.         a.objid = @objid and o.id = a.before_image_objid
  27151.     if @oldname is not null
  27152.         begin
  27153.            exec @retcode = sp_MShelpalterbeforetable @objid, @oldname
  27154.            if @@error<>0 or @retcode<>0 return (1)
  27155.            return(0)
  27156.         end
  27157. -- If this table is not involved with any filters or join filters, don't bother
  27158.     if not exists (select * from sysmergesubsetfilters where art_nickname = @tablenick
  27159.         or join_nickname = @tablenick) and
  27160.         not exists (select * from sysmergearticles where nickname = @tablenick and
  27161.             datalength (subset_filterclause) > 1)
  27162.         return(0)
  27163.     
  27164. -- Generate a unique name for our new table
  27165.     set @nameguid = newid()
  27166.     exec @retcode = dbo.sp_MSguidtostr @nameguid, @newname out
  27167.     if @@ERROR <>0 OR @retcode <>0 return (1)
  27168.     set @newname = 'MS_bi' + @newname
  27169.  
  27170. -- Call xp_execresultset with helper function command
  27171.     set @objidstr = convert(nvarchar(12), @objid)
  27172.     set @dbname = db_name()
  27173.  
  27174.        set @command = 'exec dbo.sp_MShelpcreatebeforetable '  + @objidstr + ', ''' + @newname + '''' 
  27175.        exec @retcode = master..xp_execresultset @command, @dbname
  27176.        if @@error<>0 or @retcode<>0 return (1)
  27177.  
  27178.     select @before_rowguidname=name from syscolumns where id=@objid and columnproperty(@objid, name , 'isrowguidcol')=1
  27179.  
  27180.     if @before_rowguidname is not NULL
  27181.         begin
  27182.                exec ('grant select (' + @before_rowguidname + ') on ' + @newname + ' to public')
  27183.                if @@ERROR<>0 return (1)
  27184.         end
  27185.  
  27186.     /* grant select to system_delete column */
  27187.        exec ('grant select (system_delete, generation), update(generation), delete on ' + @newname + ' to public')
  27188.        if @@ERROR<>0 return (1)
  27189.  
  27190.        exec dbo.sp_MS_marksystemobject @newname
  27191.     if @@ERROR<>0 return (1)
  27192.  
  27193.     update sysmergearticles set before_image_objid = object_id( @newname )
  27194.         where objid = @objid
  27195.  
  27196.     return(0)
  27197. go
  27198. exec dbo.sp_MS_marksystemobject sp_MScreatebeforetable 
  27199. go
  27200.  
  27201. create procedure sp_MShelpcreatebeforetable
  27202.     @objid int,
  27203.     @newname sysname
  27204. AS
  27205.     declare @command nvarchar(1000)
  27206.     declare @retcode int
  27207.     declare @include int
  27208.     declare @tablenick int
  27209.     declare @colpat nvarchar(130)
  27210.     declare @colname nvarchar(140)
  27211.     declare @typename nvarchar(140)
  27212.     declare @colid smallint
  27213.     declare @colidstr nvarchar(3)
  27214.     declare @status tinyint
  27215.     declare @len smallint
  27216.     declare @prec smallint
  27217.     declare @scale int
  27218.     declare @isnullable tinyint
  27219.     declare @cMaxIndexLength int
  27220.  
  27221.     set @cMaxIndexLength= 900  -- max index column size in SQL 2000
  27222.  
  27223.     set nocount on
  27224.  
  27225.     select @tablenick = max(nickname) from sysmergearticles where objid = @objid
  27226.     if @tablenick is null 
  27227.     begin
  27228.         select 'a' = 'raiserror (''Error creating before image table'' , 16, -1)'
  27229.         return (1)
  27230.     end
  27231.         
  27232.     -- create temp table to select the command text out of
  27233.     create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  27234.  
  27235.     set @command = 'create table ' + @newname + '('
  27236.     insert into #tempcmd (phase, cmdtext) values (1, @command)
  27237.     
  27238.     -- Loop over the columns and see which ones we include
  27239.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length,
  27240.          prec, scale, isnullable, colid from syscolumns
  27241.     where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid
  27242.     FOR READ ONLY
  27243.     
  27244.     open col_cursor
  27245.     fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  27246.     while (@@fetch_status <> -1)
  27247.     begin
  27248.         set @include = 0
  27249.         set @colpat = '%' + @colname + '%'
  27250.         if columnproperty( @objid, @colname , 'isrowguidcol')=1
  27251.         begin
  27252.             set @include = 1
  27253.         end
  27254.         else
  27255.         begin
  27256.             -- does updating this column change membership in a partial replica? 
  27257.             if exists (select * from sysmergearticles 
  27258.                 where objid = @objid and subset_filterclause like @colpat)
  27259.                 set @include = 1
  27260.             else if exists (select * from sysmergesubsetfilters
  27261.                 where art_nickname = @tablenick and join_filterclause like @colpat)
  27262.                 set @include = 1
  27263.             else if exists (select * from sysmergesubsetfilters
  27264.                  where join_nickname = @tablenick and join_filterclause like @colpat)
  27265.                 set @include = 1
  27266.         end
  27267.         -- If we want this column, map its type and insert a row to temp table
  27268.         if @include = 1
  27269.         begin
  27270.             if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  27271.                 set @len = @len/2
  27272.             exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale            
  27273.             if @@ERROR<>0 or @retcode<>0 goto Failure
  27274.             if @typename not in ('text', 'ntext','image')
  27275.             begin
  27276.                 select @colname = N'[' + replace(@colname, N']', N']]') + N']'
  27277.     
  27278.                 if @isnullable = 1
  27279.                     set @command = @colname + ' ' + @typename + ' NULL, '
  27280.                 else
  27281.                     set @command = @colname + ' ' + @typename + ' NOT NULL, '
  27282.                 
  27283.                 -- Insert the part of create table command for this column
  27284.                 insert into #tempcmd (phase, cmdtext) values (1, @command)
  27285.  
  27286.                 -- Insert a create index command if column is not too long
  27287.                 if (@len <= @cMaxIndexLength)
  27288.                 begin
  27289.                     set @colidstr =convert(nvarchar(3), @colid)
  27290.                     set @command = 'create index ' + @newname + '_' + @colidstr + ' on ' + @newname + ' (' + @colname + ') '
  27291.                     insert into #tempcmd (phase, cmdtext) values (2, @command)
  27292.                 end
  27293.             end
  27294.         end
  27295.         /* Repeat the loop with next column */
  27296.         fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  27297.     end
  27298.  
  27299.     close col_cursor
  27300.     deallocate col_cursor
  27301.  
  27302.     -- Insert last column, generation
  27303.     set @command = 'generation int NOT NULL, system_delete bit default(0))
  27304.         '
  27305.     insert into #tempcmd (phase, cmdtext) values (1, @command)
  27306.     set @command = 'create clustered index ' + @newname + '_gen on ' + @newname + '(generation) 
  27307.         '
  27308.     insert into #tempcmd (phase, cmdtext) values (2, @command)
  27309.         
  27310.     select cmdtext from #tempcmd order by phase, step
  27311.     drop table #tempcmd
  27312.  
  27313.     return(0)
  27314. Failure:
  27315.     close col_cursor
  27316.     deallocate col_cursor
  27317.     return(1)
  27318. go
  27319. exec dbo.sp_MS_marksystemobject sp_MShelpcreatebeforetable 
  27320. go
  27321.  
  27322.  
  27323. create procedure sp_MShelpalterbeforetable
  27324.     @objid int,
  27325.     @biname sysname
  27326. AS
  27327.     declare @command nvarchar(4000)
  27328.     declare @retcode int
  27329.     declare @include int
  27330.     declare @tablenick int
  27331.     declare @colpat nvarchar(130)
  27332.     declare @colname nvarchar(130)
  27333.     declare @typename sysname
  27334.     declare @colid smallint
  27335.     declare @colidstr nvarchar(3)
  27336.     declare @status tinyint
  27337.     declare @len smallint
  27338.     declare @prec smallint
  27339.     declare @scale int
  27340.     declare @isnullable tinyint
  27341.     declare @bi_objid int
  27342.     set nocount on
  27343.     declare @cMaxIndexLength int
  27344.  
  27345.     set @cMaxIndexLength= 900  -- max index column size in SQL 2000
  27346.  
  27347.     select @tablenick = max(nickname) from sysmergearticles where objid = @objid
  27348.     if @tablenick is null 
  27349.         return (1)
  27350.  
  27351.     select @bi_objid = OBJECT_ID(@biname)        
  27352.     
  27353.     -- Loop over the columns and see which ones we include
  27354.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length,
  27355.          prec, scale, isnullable, colid from syscolumns
  27356.     where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid
  27357.     FOR READ ONLY
  27358.     
  27359.     open col_cursor
  27360.     fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  27361.     while (@@fetch_status <> -1)
  27362.         begin
  27363.         set @include = 0
  27364.         set @colpat = '%' + @colname + '%'
  27365.  
  27366.         if not exists (select * from syscolumns where id = @bi_objid and QUOTENAME(name) = QUOTENAME('system_delete'))
  27367.             begin
  27368.                 set @command = 'alter table ' + @biname + ' ADD system_delete bit default(0) '
  27369.                 execute ( @command )
  27370.                 if @@ERROR<>0 
  27371.                     goto errlabel
  27372.  
  27373.                 /* grant select to system_delete column */
  27374.                    exec ('grant select (system_delete) on ' + @biname + ' to public')
  27375.                    if @@ERROR<>0 
  27376.                     goto errlabel
  27377.  
  27378.                     
  27379.             end
  27380.  
  27381.         exec ('grant select (generation), update(generation), delete on ' + @biname + ' to public')
  27382.                    if @@ERROR<>0 
  27383.                     goto errlabel
  27384.  
  27385.         -- Is this column already in the before image table?
  27386.         -- or the column is not in the vertical partitioning?
  27387.         if exists (select * from syscolumns where id = @bi_objid and name = @colname) OR
  27388.             exists (select * from sysmergearticles where objid=@objid and not exists (
  27389.                 select * from syscolumns where id = sync_objid and name = @colname))
  27390.             begin
  27391.             goto fetchnext
  27392.             end
  27393.  
  27394.         -- does updating this column change membership in a partial replica? 
  27395.         if exists (select * from sysmergearticles 
  27396.             where objid = @objid and subset_filterclause like @colpat)
  27397.             set @include = 1
  27398.         else if exists (select * from sysmergesubsetfilters
  27399.             where art_nickname = @tablenick and join_filterclause like @colpat)
  27400.             set @include = 1
  27401.         else if exists (select * from sysmergesubsetfilters
  27402.             where join_nickname = @tablenick and join_filterclause like @colpat)
  27403.             set @include = 1
  27404.  
  27405.         -- If we want this column, map its type and insert a row to temp table
  27406.         if @include <> 1
  27407.             begin
  27408.             goto fetchnext
  27409.             end
  27410.         if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes
  27411.             set @len = @len/2
  27412.         exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale
  27413.         if @@ERROR<>0 or @retcode<>0 
  27414.             goto errlabel
  27415.         if @typename not in ('text', 'ntext','image')
  27416.         begin
  27417.             set @colname = QUOTENAME(@colname)
  27418.     
  27419.             -- Always make columns nullable when we add them because we might have
  27420.             -- existing rows in the before image table.
  27421.  
  27422.             set @command = 'alter table ' + @biname + ' ADD ' + @colname + ' ' + @typename + ' NULL '
  27423.         
  27424.             execute ( @command )
  27425.             if @@ERROR<>0 goto errlabel
  27426.  
  27427.             -- Insert a create index command if column is not too long
  27428.             if (@len <= @cMaxIndexLength)
  27429.             begin
  27430.                 set @colidstr =convert(nvarchar(3), @colid)
  27431.                  set @command = 'create index ' + @biname + '_' + @colidstr + ' on ' + @biname + ' (' + @colname + ')'
  27432.                 execute ( @command )
  27433.                 if @@ERROR<>0 goto errlabel
  27434.             end
  27435.         end
  27436.                             
  27437. fetchnext:
  27438.         /* Repeat the loop with next column */
  27439.         fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid
  27440.         end
  27441.     close col_cursor
  27442.     deallocate col_cursor    
  27443.     return 0
  27444. errlabel:
  27445.     close col_cursor
  27446.     deallocate col_cursor    
  27447.     return 1
  27448.  
  27449. go
  27450.  
  27451. exec dbo.sp_MS_marksystemobject sp_MShelpalterbeforetable 
  27452. go
  27453.  
  27454. create procedure sp_MSgetbeforetableinsert
  27455.     @objid int,
  27456.     @inscommand nvarchar(2000) output
  27457. AS
  27458.     declare @before_objid int
  27459.     declare @before_name sysname
  27460.     declare @collist nvarchar(1000)
  27461.     declare @colname sysname
  27462.  
  27463.     -- Do we have a before table?
  27464.     select @before_objid = max(before_image_objid) from  sysmergearticles where objid = @objid and
  27465.             before_image_objid is not null
  27466.     select @before_name = OBJECT_NAME(@before_objid)
  27467.  
  27468.     if @before_name is null
  27469.         begin
  27470.         set @inscommand = ''
  27471.         return 0
  27472.         end
  27473.  
  27474.     set @collist = ''
  27475.     -- Loop over columns to make the column list for the insert / select command
  27476.     declare col_cursor CURSOR LOCAL FAST_FORWARD for select name from syscolumns
  27477.     where id = @before_objid and name <> 'generation' and name <> 'system_delete' order by colid
  27478.     FOR READ ONLY
  27479.  
  27480.     open col_cursor
  27481.  
  27482.     fetch next from col_cursor into @colname
  27483.     while (@@fetch_status <> -1)
  27484.         begin
  27485.         set @collist = @collist + QUOTENAME(@colname) + ', '
  27486.         fetch next from col_cursor into @colname
  27487.         end
  27488.     close col_cursor
  27489.     deallocate col_cursor
  27490.  
  27491.     -- Our list has all of the columns except generation since that gets set to a local variable
  27492.     -- Make the insert command
  27493.     set @inscommand = 'insert into ' + QUOTENAME(@before_name) + ' ( ' + @collist +
  27494.         ' generation) select ' + @collist + ' a.gen_cur from deleted, (select top 1 nickname, gen_cur = isnull(gen_cur, 0) from sysmergearticles where nickname = @tablenick) as a '
  27495.  
  27496.     return 0
  27497.     
  27498. go
  27499. exec dbo.sp_MS_marksystemobject sp_MSgetbeforetableinsert 
  27500. go
  27501.  
  27502. create procedure sp_MSfixupbeforeimagetables(@pubid uniqueidentifier)
  27503. AS
  27504. begin
  27505.     -- This procedure updates the generations in the existing rows in the before-image
  27506.     -- tables of all articles in the specified publication to the current gen_cur value for 
  27507.     -- the respective article.
  27508.     -- This is done after the subscription has been reinitialized (at a republisher). The reason
  27509.     -- is that the genhistory rows at the subscriber no longer correspond to the values before 
  27510.     -- the reinit. They are simply bcp-ed in from the bcp generated at the publisher. 
  27511.     -- Setting the existing before image rows to gen_cur has the effect of avoiding the retention-
  27512.     -- based cleanup of these rows based on invalid coldate values (since they are in context of
  27513.     -- the publisher). The cleanup thus gets delayed to when the current gen_cur value expires retention.
  27514.     declare @before_image_tablename sysname, @gencur int, @gencur_str nvarchar(20), @cmd nvarchar(256)
  27515.  
  27516.     if @pubid is null
  27517.         return 0
  27518.  
  27519.     declare beforeimagetables_cursor CURSOR LOCAL FAST_FORWARD for 
  27520.     select distinct object_name(before_image_objid), gen_cur 
  27521.     from sysmergearticles 
  27522.     where artid in 
  27523.         (select artid from sysmergearticles where pubid = @pubid)
  27524.     and before_image_objid is not null
  27525.     FOR READ ONLY
  27526.  
  27527.     open beforeimagetables_cursor
  27528.     fetch next from beforeimagetables_cursor into @before_image_tablename, @gencur
  27529.  
  27530.     while (@@fetch_status <> -1)
  27531.     begin
  27532.         
  27533.         if @before_image_tablename is not null
  27534.         begin
  27535.             select @gencur_str = convert(nvarchar(20), @gencur)
  27536.             select @cmd = 'update ' + @before_image_tablename + ' set generation = ' + @gencur_str
  27537.             exec (@cmd)
  27538.         end
  27539.         
  27540.         fetch next from beforeimagetables_cursor into @before_image_tablename, @gencur
  27541.     end
  27542.  
  27543.     close beforeimagetables_cursor
  27544.     deallocate beforeimagetables_cursor
  27545.  
  27546.     return 0
  27547. end
  27548.  
  27549. go
  27550. exec dbo.sp_MS_marksystemobject sp_MSfixupbeforeimagetables 
  27551. go
  27552. grant exec on dbo.sp_MSfixupbeforeimagetables to public
  27553. go
  27554.  
  27555. create procedure sp_MSreplcheck_permission(
  27556.     @objid int,
  27557.     @type int,
  27558.     @permissions int)
  27559. AS
  27560.     declare @tablename sysname
  27561.     declare @ownername    sysname
  27562.  
  27563.     select @ownername=user_name(uid) from sysobjects where id=@objid
  27564.     select @tablename=object_name(@objid)
  27565.  
  27566.     -- bypass this checking for dbo or member of db_owner.
  27567.     if is_srvrolemember('sysadmin') = 1 or is_member ('db_owner') = 1
  27568.         return (0)
  27569.         
  27570.     if @permissions=0
  27571.         return (0)
  27572.  
  27573.     --insert
  27574.     if @type=1 and @permissions & 1 = 1 and permissions(@objid) & 0x8=0
  27575.         return (1)
  27576.         
  27577.     --update        
  27578.     if @type=2 and @permissions & 2 = 2 and permissions(@objid) & 0x2=0
  27579.         return (1)
  27580.  
  27581.     --delete
  27582.     if @type=3 and @permissions & 4 = 4 and permissions(@objid) & 0x10=0
  27583.         return (1) 
  27584.         
  27585.     return (0)
  27586. GO
  27587. grant exec on sp_MSreplcheck_permission to public
  27588. go
  27589. exec dbo.sp_MS_marksystemobject sp_MSreplcheck_permission
  27590. go
  27591.  
  27592. create procedure sp_MSinserterrorlineage 
  27593.     (@tablenick int, 
  27594.      @rowguid uniqueidentifier,
  27595.      @lineage varbinary(255))
  27596. as
  27597.     if exists (select * from MSmerge_errorlineage where tablenick = @tablenick and
  27598.                 rowguid = @rowguid)
  27599.             update MSmerge_errorlineage set lineage = @lineage where tablenick = @tablenick and
  27600.                 rowguid = @rowguid
  27601.     else
  27602.             insert into MSmerge_errorlineage (tablenick, rowguid, lineage) 
  27603.                 values (@tablenick, @rowguid, @lineage)
  27604.     if @@ERROR <> 0 return (1)
  27605.  
  27606.     return 0
  27607. go
  27608. grant exec on sp_MSinserterrorlineage to public
  27609. go
  27610. exec dbo.sp_MS_marksystemobject sp_MSinserterrorlineage 
  27611. go
  27612. create procedure sp_MSevalsubscriberinfo 
  27613.     (@pubid uniqueidentifier)
  27614. as
  27615.     declare @expr nvarchar(500)
  27616.     select @expr = validate_subscriber_info from sysmergepublications  where pubid = @pubid
  27617.     exec ('select ' + @expr)
  27618.     if @@error<>0 return(1)
  27619.     
  27620.     return(0)
  27621. go
  27622.  
  27623. grant exec on sp_MSevalsubscriberinfo to public
  27624. go
  27625. exec dbo.sp_MS_marksystemobject sp_MSevalsubscriberinfo 
  27626. go
  27627.  
  27628. create procedure sp_MSsetsubscriberinfo 
  27629.     (@pubid uniqueidentifier, @expr nvarchar(500))
  27630. as
  27631.     update sysmergepublications set validate_subscriber_info = @expr where pubid = @pubid
  27632. go
  27633.  
  27634. grant exec on sp_MSsetsubscriberinfo to public
  27635. go
  27636. exec dbo.sp_MS_marksystemobject sp_MSsetsubscriberinfo 
  27637. go
  27638. create procedure sp_MSgetsubscriberinfo 
  27639.     (@pubid uniqueidentifier)
  27640. as
  27641.     declare @expr nvarchar(500)
  27642.     select @expr = validate_subscriber_info from sysmergepublications  where pubid = @pubid
  27643.     -- Return the value --
  27644.     select @expr
  27645. go
  27646.  
  27647. grant exec on sp_MSgetsubscriberinfo to public
  27648. go
  27649. exec dbo.sp_MS_marksystemobject sp_MSgetsubscriberinfo 
  27650. go
  27651.  
  27652. raiserror('Creating procedure sp_MSmakectsview', 0,1)
  27653. GO
  27654.  
  27655. create procedure sp_MSmakectsview
  27656.     @publication sysname,
  27657.     @ctsview     sysname,
  27658.     @dynamic_snapshot_views_table_name sysname = null
  27659. AS
  27660.     set nocount on
  27661.     declare @pubid          uniqueidentifier
  27662.     declare @artid          uniqueidentifier
  27663.     declare @pubidstr        nvarchar(40)
  27664.     declare @artidstr        nvarchar(40)
  27665.     declare @objid        int
  27666.     declare @tablenick    int
  27667.     declare @new_inactive int
  27668.     declare @new_active int
  27669.     declare @tablenickstr nvarchar(12)
  27670.     declare @command_piece nvarchar(2000)
  27671.     declare @rowguidcolname nvarchar(140)
  27672.     declare @view_type    int
  27673.     declare    @view_name  nvarchar(270)
  27674.     declare @or_after_first nvarchar(100)
  27675.     declare @select_command nvarchar(4000)
  27676.     declare @retcode int 
  27677.     declare @generate_per_article bit 
  27678.     declare @newidstr       nvarchar(40)
  27679.     declare @newid          uniqueidentifier
  27680.  
  27681.     /* By default the @generate_per_article is OFF */
  27682.       set @generate_per_article = 0
  27683.  
  27684.       set @new_inactive = 5 /* value of SQLDMOArtStat_New_Inactive */
  27685.       set @new_active = 6 /* value of SQLDMOArtStat_New_Active */
  27686.  
  27687.     if @ctsview IS NULL
  27688.         set @generate_per_article = 1
  27689.     
  27690.     select @retcode = 0
  27691.     set @or_after_first = ''
  27692.  
  27693.     select @pubid = pubid from sysmergepublications where name = @publication 
  27694.         and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name()
  27695.  
  27696.     select @newid = newid()
  27697.     exec @retcode = dbo.sp_MSguidtostr @newid, @newidstr out
  27698.     if @@ERROR <>0 OR @retcode <> 0
  27699.         return (1)
  27700.     exec @retcode = dbo.sp_MSguidtostr @pubid, @pubidstr out
  27701.     if @@ERROR <>0 OR @retcode <> 0 
  27702.         return (1)
  27703.  
  27704.     /* Check for the no filtering cases */
  27705.     if not exists (select * from sysmergesubsetfilters where pubid = @pubid) and
  27706.        not exists (select * from sysmergearticles where pubid = @pubid and
  27707.                        len(subset_filterclause) > 0)
  27708.            begin
  27709.             if @generate_per_article = 1
  27710.                 begin
  27711.                     set @ctsview = 'ctsv_' + @newidstr
  27712.                     select @command_piece = N'if object_id(''' + @ctsview + ''') is NOT NULL drop view ' + @ctsview 
  27713.                     exec ( @command_piece )
  27714.                     if @@ERROR <>0 
  27715.                         return (1)
  27716.                     exec ( @command_piece )
  27717.                 end
  27718.             set @command_piece = 'create view ' + @ctsview + ' as select * from dbo.MSmerge_contents '
  27719.  
  27720.             /* Are there any published tables not in this publication - any articles that needs to be excluded */
  27721.             if exists (select * from sysmergearticles where ((pubid=@pubid 
  27722.                 and (status=@new_inactive or  status=@new_active))
  27723.                 or (pubid <> @pubid and nickname not in (select nickname from sysmergearticles where pubid = @pubid))))
  27724.                 begin
  27725.                     /* pubidstr is needed in GUID format */
  27726.                     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  27727.                     set @command_piece = @command_piece + ' where tablenick in
  27728.                         (select nickname from sysmergearticles where status<>5 and status<>6 and pubid = ' + @pubidstr + ')' 
  27729.                     --5 and 6 are the new article statuses 
  27730.                 end                        
  27731.                         
  27732.             if @generate_per_article = 1
  27733.                 begin
  27734.                     exec ( @command_piece )
  27735.                     if @@ERROR <>0 
  27736.                         return (1)
  27737.                     select @ctsview
  27738.                 end
  27739.             else
  27740.                 begin
  27741.                     /* Now select our simple view syntax and we are done with this simple unfiltered case */
  27742.                     select @command_piece
  27743.                 end
  27744.             return 0
  27745.            end
  27746.     /* create temp table to insert into and select commands out of */
  27747.     create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  27748.  
  27749.     if @generate_per_article = 0
  27750.         begin
  27751.             set @command_piece = 'create view ' + @ctsview + ' as select * from dbo.MSmerge_contents where '
  27752.             insert into #tempcmd (phase, cmdtext) values (1, @command_piece)
  27753.         end            
  27754.  
  27755.     /* Initialize for loop over articles in this publication */
  27756.     select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid and status<>@new_active and status<>@new_inactive
  27757.     while @tablenick is not null
  27758.         begin
  27759.         if @dynamic_snapshot_views_table_name is null or @dynamic_snapshot_views_table_name = N''
  27760.         begin
  27761.             select @objid = objid, @view_type = view_type, @view_name = object_name(sync_objid) from 
  27762.                 sysmergearticles where pubid = @pubid and nickname = @tablenick 
  27763.         end
  27764.         else
  27765.         begin
  27766.             select @select_command = '
  27767.                 select @objid = sma.objid, 
  27768.                        @view_type = sma.view_type, 
  27769.                        @view_name = dsvt.dynamic_snapshot_view_name 
  27770.                   from sysmergearticles sma
  27771.                 inner join ' + @dynamic_snapshot_views_table_name + ' dsvt 
  27772.                     on dsvt.artid = sma.artid            
  27773.                  where pubid = @pubid 
  27774.                    and nickname = @tablenick'
  27775.             exec sp_executesql @select_command,
  27776.                                N'@objid int output, 
  27777.                                  @view_type int output, 
  27778.                                  @view_name nvarchar(270) output,
  27779.                                  @pubid uniqueidentifier,
  27780.                                  @tablenick int',
  27781.                                @objid = @objid output,
  27782.                                @view_type = @view_type output, 
  27783.                                @view_name = @view_name output,
  27784.                                @pubid = @pubid,
  27785.                                @tablenick = @tablenick  
  27786.             if @@error<>0 return(1)
  27787.         end
  27788.         select @rowguidcolname = name from syscolumns where id = @objid and
  27789.                 columnproperty(id, name, 'isrowguidcol')=1
  27790.  
  27791.         set @rowguidcolname = QUOTENAME(@rowguidcolname)
  27792.         set @view_name = QUOTENAME(@view_name)
  27793.         set @tablenickstr = convert(nchar(12), @tablenick)
  27794.         
  27795.         if @view_type <> 0
  27796.             begin
  27797.                 if @generate_per_article = 0
  27798.                     begin
  27799.                         set @command_piece = @or_after_first + ' 
  27800.                         (tablenick = ' + @tablenickstr + ' and rowguid in
  27801.                             (select ' + @rowguidcolname + ' from ' + @view_name + '))'
  27802.                     end
  27803.                 else
  27804.                     begin
  27805.                         select @artid = artid from sysmergearticles where nickname = @tablenick and pubid = @pubid
  27806.                         set @artidstr = '''' + convert(nchar(36), @artid) + '''' 
  27807.                         exec @retcode = dbo.sp_MSguidtostr @artid, @artidstr out
  27808.                         if @@ERROR <>0 OR @retcode <> 0 
  27809.                             return (1)
  27810.                         set @ctsview = 'ctsv_' + @newidstr + @artidstr
  27811.                         select @command_piece = N'if object_id(''' + @ctsview + ''') is NOT NULL drop view ' + @ctsview 
  27812.                         exec ( @command_piece )
  27813.                         if @@ERROR <>0 
  27814.                             return (1)
  27815.  
  27816.                         set @command_piece = 'create view dbo.' + @ctsview + 
  27817.                             ' as select * from dbo.MSmerge_contents where (tablenick = ' + @tablenickstr + ' and rowguid in
  27818.                             (select ' + @rowguidcolname + ' from ' + @view_name + ')) '
  27819.                         exec ( @command_piece )
  27820.                         if @@ERROR <>0 
  27821.                             return (1)
  27822.                     end
  27823.                     
  27824.             end                    
  27825.         else
  27826.             set @command_piece = @or_after_first + ' 
  27827.             (tablenick = ' + @tablenickstr + ')'
  27828.  
  27829.         if @generate_per_article = 0
  27830.             begin
  27831.                 insert into #tempcmd (phase, cmdtext) values (2, @command_piece)
  27832.             end
  27833.         else
  27834.             begin
  27835.                 insert into #tempcmd (phase, cmdtext) values (2, @ctsview)
  27836.             end
  27837.         
  27838.         /* Advance to next article and repeat the loop */
  27839.         select @tablenick = min(nickname) from sysmergearticles where
  27840.             pubid = @pubid and nickname > @tablenick and status<>@new_active and status<>@new_inactive
  27841.  
  27842.         /* make it so that any subsequent selects in the view are preceded by the word UNION */
  27843.         /* using OR to replace 'UNION ALL', which is equivalent to workaround a bug */
  27844.         set @or_after_first = ' OR '
  27845.  
  27846.         end
  27847.         
  27848.     /* final steps: select out the text and drop the temp table */
  27849.     if @generate_per_article = 0
  27850.         begin
  27851.             select cmdtext from #tempcmd order by phase, step
  27852.         end            
  27853.     else
  27854.         /* Select the view names so that the caller can query them so they can be BCP out and dropped later */
  27855.         begin
  27856.             select cmdtext from #tempcmd where phase = 2 order by step 
  27857.         end            
  27858.  
  27859.     drop table #tempcmd
  27860.  
  27861.     return(0)
  27862. go
  27863. exec dbo.sp_MS_marksystemobject sp_MSmakectsview 
  27864. go
  27865. grant exec on dbo.sp_MSmakectsview to public
  27866. go
  27867.  
  27868. create procedure sp_MSinsertgenerationschemachanges
  27869.     @publication sysname
  27870. AS
  27871.     declare @mingen         int
  27872.     declare @lastrecgen        int
  27873.     declare @lastrecguid    uniqueidentifier
  27874.     declare @lastsentgen        int
  27875.     declare @lastsentguid    uniqueidentifier
  27876.     declare @db_name        sysname
  27877.     declare @repid             uniqueidentifier
  27878.     declare @pubid             uniqueidentifier
  27879.     declare @schemaversion  int 
  27880.     declare @schemaguid     uniqueidentifier
  27881.     declare @schematype     int
  27882.     declare @schematext     nvarchar(2000)
  27883.     declare @artid            uniqueidentifier
  27884.     declare @retcode        int
  27885.     set nocount on
  27886.  
  27887.     set @lastrecgen = NULL
  27888.     set @lastsentgen = NULL
  27889.     
  27890.     begin tran
  27891.     save TRAN MSinsertgenerationschemachanges    
  27892.  
  27893.     set @db_name = db_name()
  27894.     select @pubid = pubid from sysmergepublications where name = @publication and publisher = @@SERVERNAME and publisher_db = @db_name
  27895.     if @pubid IS NULL
  27896.         BEGIN
  27897.             RAISERROR (20026, 16, -1, @publication)
  27898.             RETURN (1)
  27899.         END
  27900.     
  27901.     SELECT @repid = subid FROM sysmergesubscriptions where pubid = @pubid and subid = @pubid
  27902.     if @repid is NULL
  27903.         begin
  27904.             RAISERROR(20021, 16, -1)
  27905.             return (1)
  27906.         end
  27907.  
  27908.     select @mingen = min(generation) from dbo.MSmerge_genhistory where guidlocal = '00000000-0000-0000-0000-000000000000'
  27909.     if @mingen IS NOT NULL
  27910.         select @lastrecgen = max(generation) from dbo.MSmerge_genhistory where generation < @mingen
  27911.     if @lastrecgen IS NOT NULL
  27912.         begin
  27913.             select @lastrecguid = guidsrc from dbo.MSmerge_genhistory where generation = @lastrecgen
  27914.  
  27915.             set @artid = NULL
  27916.             set @schematype = 5 /* last rec gen schema type */
  27917.             select @schematext = 'exec dbo.sp_MSsetlastrecgen ' + '''' + convert(nchar(36), @repid) + ''''  + ',' + '''' + convert(nvarchar(10), @lastrecgen) + '''' + ',' + '''' + convert(nchar(36), @lastrecguid) + ''''
  27918.  
  27919.             if exists (select *    from sysmergeschemachange
  27920.                     where pubid = @pubid 
  27921.                     AND schematype = @schematype)
  27922.                 begin
  27923.                     /* Select the existing schema guid */
  27924.                     select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange
  27925.                         where pubid = @pubid 
  27926.                         AND schematype = @schematype
  27927.                     /*
  27928.                     ** Update the schema change version
  27929.                     */
  27930.                     exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, 
  27931.                         @schemaguid, @schematype, @schematext
  27932.                     if @@error <> 0    or @retcode <> 0
  27933.                         goto FAILURE
  27934.                 end
  27935.             else        
  27936.                 begin
  27937.                     /* Insert the schema change */
  27938.                     select @schemaversion = schemaversion from sysmergeschemachange
  27939.                     if (@schemaversion is NULL)
  27940.                         set @schemaversion = 1
  27941.                     else
  27942.                         select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  27943.                         
  27944.                     /* generate a new schema guid */
  27945.                     set @schemaguid = newid()
  27946.                     exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, 
  27947.                         @schemaguid, @schematype, @schematext
  27948.                     if @@error <> 0    or @retcode <> 0
  27949.                         goto FAILURE
  27950.                 end                
  27951.  
  27952.         end        
  27953.  
  27954.     select @lastsentgen = max(generation) from dbo.MSmerge_genhistory
  27955.         where guidlocal <> '00000000-0000-0000-0000-000000000000' and (art_nick = 0 or art_nick is NULL or
  27956.             art_nick in (select nickname from sysmergearticles where pubid = @pubid))
  27957.  
  27958.     if @lastsentgen IS NOT NULL
  27959.         begin
  27960.             select @lastsentguid = guidsrc from dbo.MSmerge_genhistory where generation = @lastsentgen
  27961.             set @artid = NULL
  27962.             set @schematype = 6 /* last sent gen schema type */
  27963.             select @schematext = 'exec dbo.sp_MSsetlastsentgen ' + '''' + convert(nchar(36), @repid) + ''''  + ',' + '''' + convert(nvarchar(10), @lastsentgen) + '''' + ',' + '''' + convert(nchar(36), @lastsentguid) + ''''
  27964.  
  27965.             if exists (select *    from sysmergeschemachange
  27966.                     where pubid = @pubid 
  27967.                     AND schematype = @schematype)
  27968.                 begin
  27969.                     /* Select the existing schema guid */
  27970.                     select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange
  27971.                         where pubid = @pubid 
  27972.                         AND schematype = @schematype
  27973.                     /*
  27974.                     ** Update the schema change version
  27975.                     */
  27976.                     exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, 
  27977.                         @schemaguid, @schematype, @schematext
  27978.                     if @@error <> 0    or @retcode <> 0
  27979.                         goto FAILURE
  27980.                 end
  27981.             else        
  27982.                 begin
  27983.                     /* Insert the schema change */
  27984.                     select @schemaversion = schemaversion from sysmergeschemachange
  27985.                     if (@schemaversion is NULL)
  27986.                         set @schemaversion = 1
  27987.                     else
  27988.                         select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange
  27989.                         
  27990.                     /* generate a new schema guid */
  27991.                     set @schemaguid = newid()
  27992.                     exec @retcode = dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, 
  27993.                         @schemaguid, @schematype, @schematext
  27994.                     if @@error <> 0    or @retcode <> 0
  27995.                         goto FAILURE
  27996.                 end                
  27997.                 
  27998.         end
  27999.     COMMIT TRAN            
  28000.     RETURN 0
  28001.  
  28002. FAILURE:
  28003.     /* UNDONE : This code is specific to 6.X nested transaction semantics */
  28004.     if @@TRANCOUNT > 0
  28005.     begin
  28006.         ROLLBACK TRANSACTION MSinsertgenerationschemachanges
  28007.         COMMIT TRANSACTION
  28008.     end
  28009.     
  28010.     RETURN 1
  28011. go
  28012.        
  28013. exec dbo.sp_MS_marksystemobject sp_MSinsertgenerationschemachanges
  28014. go
  28015.  
  28016. grant exec on dbo.sp_MSinsertgenerationschemachanges to public
  28017. go
  28018.  
  28019. CREATE PROCEDURE sp_MSalreadyhavegeneration
  28020.     (@genguid uniqueidentifier, @subscribernick int)
  28021. as
  28022.     declare @nicknames varbinary(1000)
  28023.     declare @offset int
  28024.     
  28025.     /*
  28026.     ** Check input parameter
  28027.     */
  28028.     if (@genguid is null)
  28029.         begin
  28030.             RAISERROR(14043, 16, -1, '@genguid')
  28031.             return (1)
  28032.         end
  28033.  
  28034.     select @nicknames = nicknames from dbo.MSmerge_genhistory where guidsrc = @genguid
  28035.     if @nicknames is null
  28036.         begin
  28037.             -- what is the appropriate error to return?
  28038.             RAISERROR(21333, 16, -1)
  28039.             return (1)
  28040.         end
  28041.  
  28042.     set @offset = 1
  28043.     while @offset < len(@nicknames)
  28044.         begin
  28045.             -- If the subscriber nickname is already in the list just return
  28046.             if (convert(int, substring(@nicknames, @offset, 4)) = @subscribernick)
  28047.                 return (0)
  28048.             set @offset = @offset + 4
  28049.         end
  28050.     -- Subscriber nickname is not in the array.  Add it so that we won't send this gen
  28051.     -- back down in the return message.  (Would waste bandwidth...)
  28052.     set @nicknames = convert(binary(4), @subscribernick) + @nicknames
  28053.     update dbo.MSmerge_genhistory set nicknames = @nicknames where guidsrc = @genguid
  28054.     
  28055.     return (0)
  28056. go
  28057. exec dbo.sp_MS_marksystemobject sp_MSalreadyhavegeneration
  28058. go
  28059. grant exec on dbo.sp_MSalreadyhavegeneration to public
  28060. GO
  28061.  
  28062.  
  28063. CREATE PROCEDURE sp_MSgettablecontents 
  28064.     @pubid uniqueidentifier
  28065. as 
  28066.     declare @tablenick             int
  28067.     declare @new_active            int
  28068.     declare @new_inactive        int
  28069.     declare @artname            sysname
  28070.     declare @view_name            nvarchar(60)
  28071.     declare @rowguidcolname        sysname
  28072.     declare @sync_viewname        sysname
  28073.     declare @quoted_sync_viewname nvarchar(144)
  28074.     declare @quoted_view_name    nvarchar(144)
  28075.     declare @nickname            int
  28076.     declare @objid                 int
  28077.     
  28078.     declare @tablenickstr nvarchar(12)
  28079.     
  28080.     select @new_inactive = 5 --special article status for adding article after snapshot
  28081.     select @new_active = 6      --special article status for adding article after snapshot
  28082.     
  28083.     select Top 1 @tablenick = nickname, @sync_viewname=object_name(sync_objid), @objid=objid, @artname=name
  28084.         from sysmergearticles where pubid = @pubid and (status=@new_inactive or status=@new_active)
  28085.                                 order by nickname ASC
  28086.     while @objid is not null
  28087.         begin
  28088.             set @tablenickstr = convert(nchar(12), @tablenick)
  28089.             select @rowguidcolname = name from syscolumns where id = @objid and columnproperty(id, name, 'isrowguidcol')=1
  28090.             select @view_name='MSmerge_contents_' + @artname
  28091.             select @quoted_view_name=QUOTENAME(@view_name)
  28092.             --Must drop the view (if exists) and recreate
  28093.             if exists (select * from sysobjects where name=@view_name and xtype = 'V')
  28094.             begin                
  28095.                 exec ('drop view ' + @quoted_view_name)
  28096.             end
  28097.             select @quoted_sync_viewname=QUOTENAME(@sync_viewname)
  28098.             exec('create view ' + @quoted_view_name + 
  28099.                 ' as select * from dbo.MSmerge_contents where (tablenick = ' + @tablenickstr + ' and rowguid in
  28100.                         (select ' + @rowguidcolname + ' from ' + @quoted_sync_viewname + '))')
  28101.  
  28102.             select @objid = NULL
  28103.             select Top 1 @tablenick = nickname,@sync_viewname=object_name(sync_objid), @objid=objid, @artname=name from sysmergearticles 
  28104.                 where pubid = @pubid and nickname>@tablenick and (status=@new_inactive or status=@new_active) 
  28105.                     order by nickname ASC
  28106.             insert #temp_table_for_systable_view(contentsview) values(@view_name)        
  28107.         end    
  28108. go
  28109.  
  28110. exec dbo.sp_MS_marksystemobject sp_MSgettablecontents
  28111. go
  28112. grant exec on dbo.sp_MSgettablecontents to public
  28113. GO
  28114.  
  28115.  
  28116. CREATE PROCEDURE sp_MSdelgenzero
  28117. as
  28118.     delete from dbo.MSmerge_contents where generation = 0 or generation = 1
  28119. go
  28120.  
  28121. exec dbo.sp_MS_marksystemobject sp_MSdelgenzero
  28122. go
  28123. grant exec on dbo.sp_MSdelgenzero to public
  28124. GO
  28125.  
  28126. --
  28127. -- Name: sp_MSmakedynsnapshotvws
  28128. --
  28129. -- Description: This procedure generates temporary sync-views on top of 
  28130. --              table articles specific to a particular dynamic filter login by
  28131. --              replacing all occurrances of the suser_sname() intrinsic 
  28132. --              function in the regular article sync-views with the specified
  28133. --              dynamic filter login value.
  28134. --
  28135. -- Parameters: @publication sysname 
  28136. --             @dynamic_filter_login sysname 
  28137. --                    
  28138. -- Notes: This procedure should be used by dynamic snapshot processing
  28139. --        only. A valid regular snapshot is assumed to have been generated
  28140. --        by the time the snapshot agent calls this procedure. If the specified
  28141. --        @dynamic_filter_login is empty or null, the current value
  28142. --        of suser_sname() will be used.
  28143. --
  28144. -- Result: sysname - article_name
  28145. --         sysname - dynamic_snapshot_view_name
  28146. --         The result set basically describes the mapping between articles and
  28147. --         the dynamic snapshot views to be used for the dynamic snapshot 
  28148. --         generation session that initiated the call. The exceptions being the
  28149. --         'dynamic snapshot view name' column of the first row is actually the
  28150. --         name of the global temporary table for tracking the dynamic snapshot
  28151. --         while the 'dynamic snapshot view name' column of the 2nd row is 
  28152. --         actually the owner name of all the generated dynamic snapshot 
  28153. --         views. (Note: all generated views belong to the same owner)       
  28154. --
  28155. -- Returns: 0 - succeeded
  28156. --          1 - failed
  28157. --
  28158. -- Security: Execute permission of this procedure is granted to public. A 
  28159. --           procedural security check is made inside the stored procedure 
  28160. --           to make sure that the caller is either a member of the 
  28161. --           'sysadmin' server role or the 'db_owner' database role.
  28162. --          
  28163. raiserror('Creating procedure sp_MSmakedynsnapshotvws', 0,1)
  28164. go
  28165. create procedure sp_MSmakedynsnapshotvws(
  28166.     @publication sysname, 
  28167.     @dynamic_filter_login sysname
  28168.     )
  28169. as
  28170. begin
  28171.     set nocount on
  28172.     declare @retcode int
  28173.     declare @dynamic_snapshot_views_table_name sysname
  28174.     declare @string_literalized_dynamic_filter_login nvarchar(4000)
  28175.     declare @articles_cursor_allocated bit, 
  28176.             @articles_cursor_opened bit
  28177.     declare @pubid uniqueidentifier
  28178.  
  28179.     select @articles_cursor_allocated = 0
  28180.     select @articles_cursor_opened = 0
  28181.     select @retcode = 0
  28182.     -- Security check
  28183.     exec @retcode = sp_MSreplcheck_publish
  28184.     if @retcode <> 0 or @@error <> 0
  28185.         return 1
  28186.  
  28187.     if @dynamic_filter_login is null or @dynamic_filter_login = N''
  28188.     begin
  28189.         select @dynamic_filter_login = suser_sname()
  28190.     end
  28191.     if @@error<>0
  28192.     begin
  28193.         return 1
  28194.     end
  28195.     select @string_literalized_dynamic_filter_login = 
  28196.         fn_replmakestringliteral(@dynamic_filter_login) collate database_default
  28197.     
  28198.     -- Compute the proper view creation order, code is copied from sp_MSpublicationview
  28199.     declare @progress int
  28200.     declare @article_level int
  28201.     select @progress = 1
  28202.     select @article_level = 0
  28203.     select @pubid = pubid 
  28204.       from sysmergepublications 
  28205.     where upper(publisher) = upper(@@servername)
  28206.       and publisher_db = db_name()
  28207.       and name = @publication
  28208.     if @pubid is null 
  28209.     begin
  28210.         raiserror(20026,11,-1,@publication)
  28211.     end
  28212.     create table #creation_order
  28213.     (
  28214.     creation_order int identity not null,
  28215.     art_nick int not null,
  28216.     article_level int not null    
  28217.     )
  28218.     if @@error<>0
  28219.     begin
  28220.         return 1
  28221.     end
  28222.     
  28223.     while @progress > 0
  28224.     begin
  28225.         insert into #creation_order(art_nick, article_level)
  28226.             select nickname, @article_level 
  28227.               from sysmergearticles
  28228.              where pubid=@pubid 
  28229.                and nickname not in (select art_nick from #creation_order)
  28230.                and nickname not in
  28231.                     (select art_nickname from sysmergesubsetfilters
  28232.                       where pubid=@pubid and join_nickname not in
  28233.                         (select art_nick from #creation_order))
  28234.         select @progress = @@rowcount
  28235.         select @article_level = @article_level + 1
  28236.     end
  28237.  
  28238.     -- Create temp table for storing the view definitions and 
  28239.     -- also for acting as a symbol table for views
  28240.     create table #view_defs_and_syms  
  28241.     (
  28242.         creation_order int identity,
  28243.         original_view_name sysname collate database_default,
  28244.         dynamic_snapshot_view_name sysname collate database_default,
  28245.         dynamic_snapshot_view_definition nvarchar(3500) collate database_default
  28246.     )      
  28247.     if @@error<>0
  28248.     begin
  28249.         return 1
  28250.     end
  28251.     -- By the time this procedure is called by the snapshot agent, a regular
  28252.     -- snapshot is assumed to have been generated.
  28253.     -- The specified publication is assumed to have dynamic filtering enabled        
  28254.     -- Open a transaction to make sure that no stale temporary views
  28255.     -- can be lying around for longer than they have to.  
  28256.     
  28257.     begin transaction
  28258.     save transaction sp_MSmakedynsnapshotartvws
  28259.  
  28260.     -- Create a global temporary table to track the sync-views
  28261.     -- that we are about to create here.
  28262.  
  28263.     select @dynamic_snapshot_views_table_name = N'##DYN_VIEWS_' + 
  28264.         replace(convert(nvarchar(36), newid()), N'-', N'_')
  28265.          
  28266.     exec('create table ' + @dynamic_snapshot_views_table_name + '
  28267.           (
  28268.           artid           uniqueidentifier primary key,
  28269.           dynamic_snapshot_view_name sysname not null unique
  28270.           )')
  28271.     if @@error<>0
  28272.     begin
  28273.         goto Failure
  28274.     end
  28275.  
  28276.     declare hArticles cursor local fast_forward for
  28277.     select artid, sync_objid 
  28278.       from sysmergearticles sma
  28279.     inner join #creation_order co 
  28280.         on sma.nickname = co.art_nick
  28281.      where sma.pubid = @pubid
  28282.     order by co.creation_order asc
  28283.     if @@error<>0
  28284.     begin
  28285.         goto Failure
  28286.     end
  28287.     select @articles_cursor_allocated = 1
  28288.     open hArticles    
  28289.     if @@error<>0
  28290.     begin
  28291.         goto Failure
  28292.     end
  28293.     select @articles_cursor_opened = 1
  28294.  
  28295.     declare @sync_objid int
  28296.     declare @artid uniqueidentifier
  28297.     declare @dynamic_snapshot_view_name sysname
  28298.     declare @original_view_name sysname 
  28299.     declare @insert_command nvarchar(4000)
  28300.     declare @script_view_command nvarchar(4000)
  28301.     declare @min_id int
  28302.     declare @db_name sysname
  28303.     declare @original_view_definition nvarchar(4000)
  28304.  
  28305.     select @db_name = db_name()
  28306.  
  28307.     -- Stage 1: Build up the symbol table with 
  28308.     -- regular sync view definitions
  28309.     fetch hArticles into @artid, @sync_objid
  28310.     
  28311.     while (@@fetch_status<>-1)
  28312.     begin
  28313.         -- Get name of the original sync view
  28314.         select @original_view_name = object_name(@sync_objid)
  28315.  
  28316.         -- Construct name for the dynamic snapshot view        
  28317.         select @dynamic_snapshot_view_name = N'DYN_VIEW_' + 
  28318.             replace(convert(nvarchar(36), newid()), N'-', N'_')
  28319.  
  28320.         -- Insert a row into the symbol and view def table 
  28321.         -- for further processing 
  28322.         select @original_view_definition = text 
  28323.           from dbo.syscomments
  28324.          where id = @sync_objid
  28325.  
  28326.         insert #view_defs_and_syms 
  28327.         values (quotename(@original_view_name), 
  28328.                 @dynamic_snapshot_view_name, 
  28329.                 @original_view_definition) 
  28330.         if @@error<>0
  28331.         begin
  28332.             goto Failure
  28333.         end
  28334.     
  28335.         select @insert_command = N'insert ' + @dynamic_snapshot_views_table_name + ' values (@artid, @dynamic_snapshot_view_name)'
  28336.         -- Insert the mapping into the global temp table
  28337.         exec @retcode = sp_executesql
  28338.             @insert_command,
  28339.             N'@artid uniqueidentifier, @dynamic_snapshot_view_name sysname',
  28340.             @artid = @artid,
  28341.             @dynamic_snapshot_view_name = @dynamic_snapshot_view_name
  28342.  
  28343.         if @@error<>0 or @retcode<>0
  28344.         begin
  28345.             goto Failure
  28346.         end
  28347.  
  28348.         -- Insert the view name into the global tracking table so it is 
  28349.         -- guaranteed to be cleaned up properly 
  28350.         insert MSdynamicsnapshotviews values (@dynamic_snapshot_view_name)
  28351.         if @@error<>0
  28352.         begin
  28353.             goto Failure
  28354.         end
  28355.  
  28356.         fetch hArticles into @artid, @sync_objid   
  28357.     end
  28358.     close hArticles
  28359.     select @articles_cursor_opened = 0
  28360.     deallocate hArticles
  28361.     select @articles_cursor_allocated = 0
  28362.     -- Stage 2: Fix-up all the internal references to non-dynamic snapshot
  28363.     --          views inside the dynamic snapshot view definitions and
  28364.     --          create the views along the way.
  28365.  
  28366.     -- Cursor state variables for ensuring proper cursor cleanup
  28367.     declare @viewdefs_cursor_allocated bit,
  28368.             @viewdefs_cursor_opened bit,
  28369.             @symbols_cursor_allocated bit,
  28370.             @symbols_cursor_opened bit
  28371.  
  28372.     declare @dynamic_snapshot_view_definition nvarchar(4000)
  28373.     declare @dynamic_snapshot_view_name_symbol sysname
  28374.     declare @qualified_dynamic_snapshot_view_name nvarchar(4000)
  28375.  
  28376.     select @viewdefs_cursor_allocated = 0,
  28377.            @viewdefs_cursor_opened = 0,
  28378.            @symbols_cursor_allocated = 0,
  28379.            @symbols_cursor_opened = 0
  28380.  
  28381.     -- Declare a cursor for each dynamic snapshot view definition
  28382.     declare hViewDefs cursor local fast_forward for
  28383.     select dynamic_snapshot_view_name,
  28384.            dynamic_snapshot_view_definition 
  28385.       from #view_defs_and_syms
  28386.     order by creation_order asc
  28387.  
  28388.     if @@error<>0
  28389.     begin
  28390.         goto Failure
  28391.     end
  28392.     select @viewdefs_cursor_allocated = 1
  28393.     
  28394.     -- Declare a static cursor for symbol lookup so we can go back to the 
  28395.     -- first row without tearing down the cursor   
  28396.     declare hSymbols cursor local static for
  28397.     select original_view_name,
  28398.            dynamic_snapshot_view_name
  28399.       from #view_defs_and_syms
  28400.     if @@error<>0
  28401.     begin
  28402.         goto Failure
  28403.     end
  28404.     select @symbols_cursor_allocated = 1
  28405.     
  28406.     open hViewDefs
  28407.     if @@error<>0
  28408.     begin
  28409.         goto Failure
  28410.     end
  28411.     select @viewdefs_cursor_opened = 1
  28412.     open hSymbols
  28413.     if @@error<>0
  28414.     begin
  28415.         goto Failure
  28416.     end
  28417.     select @symbols_cursor_opened = 1
  28418.      
  28419.     -- For each view definition...
  28420.     fetch hViewDefs into @dynamic_snapshot_view_name, 
  28421.                          @dynamic_snapshot_view_definition
  28422.     while (@@fetch_status<>-1)
  28423.     begin
  28424.  
  28425.         -- For each dynamic snapshot view name to original view name mapping...
  28426.         fetch first from hSymbols into @original_view_name,
  28427.                                        @dynamic_snapshot_view_name_symbol 
  28428.         while (@@fetch_status<>-1)
  28429.         begin
  28430.             -- Do view name replacement
  28431.             select @qualified_dynamic_snapshot_view_name = N'[dbo].' +
  28432.                 quotename(@dynamic_snapshot_view_name_symbol)
  28433.  
  28434.             select @dynamic_snapshot_view_definition =
  28435.                 replace(@dynamic_snapshot_view_definition,
  28436.                         @original_view_name,
  28437.                         @qualified_dynamic_snapshot_view_name)
  28438.             fetch hSymbols into @original_view_name,
  28439.                                 @dynamic_snapshot_view_name_symbol 
  28440.         end
  28441.         -- Replace suser_sname() with string literalized version of the given
  28442.         -- dynamic filter login 
  28443.         select @dynamic_snapshot_view_definition =
  28444.             replace(@dynamic_snapshot_view_definition collate SQL_Latin1_General_Cp1_CI_AS,
  28445.                     N'suser_sname()' collate SQL_Latin1_General_Cp1_CI_AS,
  28446.                     @string_literalized_dynamic_filter_login collate SQL_Latin1_General_Cp1_CI_AS)
  28447.  
  28448.         -- Replace system_user with string literalized version of the given
  28449.         -- dynamic filter login 
  28450.         select @dynamic_snapshot_view_definition =
  28451.             replace(@dynamic_snapshot_view_definition collate SQL_Latin1_General_Cp1_CI_AS,
  28452.                     N'system_user' collate SQL_Latin1_General_Cp1_CI_AS,
  28453.                     @string_literalized_dynamic_filter_login collate SQL_Latin1_General_Cp1_CI_AS)
  28454.         if datalength(@dynamic_snapshot_view_definition) = 7000
  28455.         begin
  28456.             raiserror(21387,16,-1)
  28457.             goto Failure
  28458.         end
  28459.  
  28460.         -- Create the view and mark it as a system object
  28461.         exec (@dynamic_snapshot_view_definition)
  28462.         if @@error<>0
  28463.         begin
  28464.             goto Failure
  28465.         end
  28466.         exec @retcode = sp_MS_marksystemobject @dynamic_snapshot_view_name
  28467.         if @@error<>0 or @retcode<>0
  28468.         begin
  28469.             goto Failure
  28470.         end
  28471.         fetch hViewDefs into @dynamic_snapshot_view_name,
  28472.                              @dynamic_snapshot_view_definition
  28473.     end
  28474.  
  28475.     close hViewDefs
  28476.     deallocate hViewDefs
  28477.     close hSymbols
  28478.     deallocate hSymbols
  28479.     drop table #view_defs_and_syms
  28480.     drop table #creation_order
  28481.     commit transaction     
  28482.  
  28483.     -- Construct the result set 
  28484.     declare @dynamic_snapshot_view_owner sysname
  28485.  
  28486.     -- Since all views will have the same owner, we may as well just 
  28487.     -- find it once and then return it in the second row of the result set
  28488.     -- (see header)    
  28489.  
  28490.     -- Note: Even the cursors are closed, the @dynamic_snapshot_view_name
  28491.     -- variable should still contain a valid value
  28492.  
  28493.     select @dynamic_snapshot_view_owner = user_name(uid) 
  28494.       from sysobjects 
  28495.      where name = @dynamic_snapshot_view_name
  28496.     declare @result_command nvarchar(4000) 
  28497.     select @result_command = '    
  28498.     select ''article_name'' = null, 
  28499.            ''dynamic_snapshot_view_name'' = ' + 
  28500.            fn_replmakestringliteral(@dynamic_snapshot_views_table_name) collate database_default + N'
  28501.     union all
  28502.     select null, ' +
  28503.            coalesce(fn_replmakestringliteral(@dynamic_snapshot_view_owner) collate database_default, N'null') collate database_default + N' 
  28504.     union all 
  28505.     select sma.name, dsvt.dynamic_snapshot_view_name
  28506.       from sysmergearticles sma
  28507.     inner join ' + @dynamic_snapshot_views_table_name + N' dsvt
  28508.       on sma.artid = dsvt.artid
  28509.     where sma.pubid = ''' + convert(nvarchar(128), @pubid) + ''''
  28510.  
  28511.     exec (@result_command)
  28512.     if @@error<>0 
  28513.         return 1
  28514.  
  28515.     return 0     
  28516. Failure:
  28517.     if @articles_cursor_opened = 1
  28518.     begin
  28519.         close hArticles
  28520.     end
  28521.     if @articles_cursor_allocated = 1
  28522.     begin
  28523.         deallocate hArticles
  28524.     end
  28525.     if @viewdefs_cursor_opened = 1
  28526.     begin
  28527.         close hViewDefs
  28528.     end
  28529.     if @viewdefs_cursor_allocated = 1
  28530.     begin
  28531.         deallocate hViewDefs
  28532.     end
  28533.     if @symbols_cursor_opened = 1
  28534.     begin
  28535.         close hSymbols
  28536.     end
  28537.     if @symbols_cursor_allocated = 1
  28538.     begin
  28539.         deallocate hSymbols
  28540.     end     
  28541.     drop table #view_defs_and_syms    
  28542.     drop table #creation_order
  28543.     rollback transaction sp_MSmakedynsnapshotartvws
  28544.     commit transaction    
  28545.     return 1
  28546. end
  28547. go
  28548. exec sp_MS_marksystemobject 'sp_MSmakedynsnapshotvws'
  28549. grant execute on sp_MSmakedynsnapshotvws to public
  28550. go
  28551. --
  28552. -- Name: sp_MSdropdynsnapshotvws
  28553. --
  28554. -- Description: This procedure is used for dropping the dynamic snapshot views
  28555. --              for a particular dynamic snapshot generation session.
  28556. --
  28557. -- Parameter: dynamic_snaphsot_views_table sysname
  28558. --
  28559. -- Returns: 0 - succeeded
  28560. --          1 - failed
  28561. --
  28562. -- Result: none
  28563. --
  28564. -- Security: Execute permission of this procedure is granted to public. 
  28565. --           Internally, this procedure will call sp_MSreplcheck_publish
  28566. --           to make sure that the caller is either server sysadmin or dbo 
  28567. --           of the publishing database.
  28568. --              
  28569. raiserror('Creating procedure sp_MSdropdynsnapshotvws', 0,1)
  28570. go
  28571. create procedure sp_MSdropdynsnapshotvws (
  28572.     @dynamic_snapshot_views_table sysname
  28573.     )
  28574. as
  28575. begin
  28576.     set nocount on
  28577.     declare @retcode int   
  28578.     declare @final_retcode int
  28579.     declare @select_command nvarchar(4000)
  28580.     declare @old_dynamic_snapshot_view_name sysname
  28581.     declare @dynamic_snapshot_view_name sysname
  28582.     declare @drop_view_command nvarchar(4000)
  28583.     declare @select_param_list nvarchar(4000)
  28584.  
  28585.     select @final_retcode = 0
  28586.     select @retcode = 0
  28587.     -- Security check 
  28588.     exec @retcode = sp_MSreplcheck_publish
  28589.     if @@error<>0 or @retcode<>0
  28590.     begin
  28591.         return 1
  28592.     end
  28593.  
  28594.     -- For the first fecth, don't do comparison with the old view name...
  28595.     select @dynamic_snapshot_view_name  = null       
  28596.     select @select_command = N'
  28597.         select @dynamic_snapshot_view_name = min(dynamic_snapshot_view_name)
  28598.           from ' + @dynamic_snapshot_views_table 
  28599.  
  28600.     select @select_param_list =         
  28601.         N'@dynamic_snapshot_view_name sysname output'
  28602.  
  28603.     exec @retcode = sp_executesql @select_command,
  28604.         @select_param_list,
  28605.         @dynamic_snapshot_view_name = @dynamic_snapshot_view_name output
  28606.     if @@error<>0 or @retcode<>0
  28607.     begin
  28608.         select @final_retcode = 1
  28609.     end
  28610.  
  28611.     -- Change query to do comparison with the old name
  28612.     select @select_command = N'
  28613.         select @dynamic_snapshot_view_name = min(dynamic_snapshot_view_name)
  28614.           from ' + @dynamic_snapshot_views_table + N' 
  28615.          where dynamic_snapshot_view_name > @old_dynamic_snapshot_view_name'
  28616.     
  28617.     select @select_param_list =         
  28618.         N'@dynamic_snapshot_view_name sysname output, 
  28619.           @old_dynamic_snapshot_view_name sysname'
  28620.  
  28621.     -- Keep selecting view with the smallest name that
  28622.     -- is greater than the last one until we are done
  28623.     while @dynamic_snapshot_view_name is not null
  28624.     begin
  28625.  
  28626.         select @drop_view_command = N'drop view ' + 
  28627.             quotename(@dynamic_snapshot_view_name)
  28628.         exec(@drop_view_command)    
  28629.         if @@error<>0
  28630.         begin
  28631.             select @final_retcode = 1 
  28632.         end
  28633.         delete MSdynamicsnapshotviews 
  28634.          where dynamic_snapshot_view_name = @dynamic_snapshot_view_name      
  28635.         if @@error<>0
  28636.         begin
  28637.             select @final_retcode = 1 
  28638.         end
  28639.  
  28640.         select @old_dynamic_snapshot_view_name = @dynamic_snapshot_view_name
  28641.         select @dynamic_snapshot_view_name = null
  28642.         exec @retcode = sp_executesql @select_command,
  28643.             @select_param_list,
  28644.             @dynamic_snapshot_view_name = @dynamic_snapshot_view_name output,
  28645.             @old_dynamic_snapshot_view_name = @old_dynamic_snapshot_view_name  
  28646.  
  28647.         if @@error<>0 or @retcode<>0
  28648.         begin
  28649.             select @final_retcode = 1
  28650.         end
  28651.     end 
  28652.     -- At the end, we need to drop the temp table
  28653.     declare @drop_table_command nvarchar(4000)
  28654.     select @drop_table_command = N'drop table ' + @dynamic_snapshot_views_table
  28655.     exec(@drop_table_command)
  28656.     if @@error<>0
  28657.     begin
  28658.         select @final_retcode = 1
  28659.     end
  28660.     return @final_retcode    
  28661. end
  28662. go
  28663. exec sp_MS_marksystemobject 'sp_MSdropdynsnapshotvws'
  28664. grant execute on sp_MSdropdynsnapshotvws to public
  28665. go
  28666. exec dbo.sp_configure 'allow updates',0
  28667.  
  28668. go
  28669.  
  28670. dump tran master with no_log
  28671. go
  28672.  
  28673.  
  28674. reconfigure with override
  28675. go
  28676.  
  28677.  
  28678.  
  28679.